数据库三范式

  • 意义:尽全力减少数据的冗余

三范式-3NF

  • 1NF:拆字段,字段是最小的粒度不能再拆分,比如:地址表中拆地址
  • 2NF:拆表,满足1NF,表中的字段必须依赖于全部主键而非部分主键,比如:商品表中商品的id和分类的id是复合主键,但是分类名仅仅依靠分类id就能索引到,所以将其拆分为 商品表、分类表、定价表
  • 3NF:拆表,满足2NF,表中非主键字段之间不能有传递性依赖,比如:商品表中仓库负责人依赖于仓库,拆表,将商品表拆分为 商品表 和 仓库表

反范式

  • 定义:适当增加数据冗余,多张表中冗余相同的字段,比如销量、地址等
  • 适当的冗余增加查询效率[冗余销量字段]
  • 适当的冗余可以保证数据真实性[订单表冗余地址相关字段]

数据导入和导出

导出[备份]-dumpdata

备份模型实例和数据库

# 备份所有数据

python3 manage.py dumpdata > xxx.json

# 备份指定应用数据

python3 manage.py dumpdata 应用名 > xxx.json

# 备份指定应用指定表数据

python3 manage.py dumpdata 应用名.表名 > xxx.json

导入[恢复]-loaddata

python3 manage.py loaddata xxx.json

静态文件路由设置

  • 配置图片类请求路由
from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

# settings.py
MEDIA_URL = "/media/"

# - 项目中创建media文件夹,并把对应商品图片拷贝到此目录
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

缓存装饰器配置

使用django自带的缓存装饰器

  • 独立缓存区域
urlpatterns = [
    path("index", cache_page(300, cache="goods_index")(views.XxxView.as_view())),
]
  • settings.py中配置缓存配置项
CACAHES = {
    "goods_index": {
        "LOCATION": "redis://127.0.0.1:6379/2"
    }
}
  • 在admin后台进行增删改数据时,admin.ModelAdmin中的save_model()方法和delete_model()方法会被调用,所以我们通过重写这两个方法,实现在增删改数据时进行整个缓存数据库的清除flushdb
# goods/admin.py

from django.core.cache import caches

INDEX_CACHE = caches["goods_index"]

@admin.register(SKU)
class XxxAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        super().save_model(request,obj, form, change)
    # 清除首页缓存
        INDEX_CACHE.clear()

    def delete_model(self, ...):
        super().delete_model(request,obj...)
    # 清除首页缓存
        INDEX_CACHE.clear()

商品装饰器

  • 进阶版可传参装饰器
from django.core.cache import caches


def cache_check(**cache_kwargs):
    def _cache_check(func):
        def wrapper(self, request, *args, **kwargs):
            """
            构建可传参的装饰器:自定义缓存key
            :param:cache_kwargs: 将装饰器的参数打包成字典
            :param:func: 被装饰的方法[get()方法]
            :param:self request *args **kwargs:方法参数[get()方法参数]
            """
            """
            cache_kwargs:{'key_prefix': 'gd', 'key_param': 'sku_id', 'cache': 'goods_detail', 'expire': 60}
            kwargs:{'sku_id': 1}
            """
            # print('cache_kwargs--->', cache_kwargs)
            # print('kwargs--->', kwargs)

            if "cache" in cache_kwargs:
                CACHES = caches[cache_kwargs["cache"]]
            else:
                CACHES = caches["default"]

            # key: gd1
            key = cache_kwargs["key_prefix"] + str(kwargs["sku_id"])

            # 先看redis中是否有缓存
            response = CACHES.get(key)
            if response:
                print("---数据来自于Redis---")
                return response

            # redis中没有,到MySQL中获取并缓存到redis
            value = func(self, request, *args, **kwargs)
            exp = cache_kwargs.get("expire", 300)
            CACHES.set(key, value, exp)

            return value
        return wrapper
    return _cache_check
  • 使用装饰器,需要配合admin.py文件中重写的save_model()方法及时更新缓存
from utils.cache_dec import cache_check

class GoodsDetailView(View):
    @cache_check(key_prefix="gd", key_param="sku_id", cache="goods_detail", expire=60)
    def get(self, request, sku_id):
        ...