完成了项目的模型层,最需要思考的是数据库该如何设计?这次的电商项目,从用户到下单,都会有哪些操作呢?当看到页面的那些商品信息或是活动促销信息,有考虑过它们之间的联系么?要是,商品的分类要像某宝或是某东,那样有二级和三级分类,这样又该怎么处理呢?如果每个功能的数据表都单独设计成和用户关联,那功能的不断扩展,会不会影响到整个数据库读写与查询呢?
完成了前一小节的主页,需要对商品详情页单独写一个视图类。会发现,在主页的视图和商品详情页视图中,都会先从缓存中去查询有无数据。
一、商品详情页
from django_redis import get_redis_connection
django_redis 在 settings.py 文件中配置
# 缓存
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/5",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
class DetailView(BaseCartView):
"""商品详细信息页面"""
def get(self, request, sku_id):
# 尝试获取缓存数据
context = cache.get("detail_%s" % sku_id)
# 如果缓存不存在
if context is None:
try:
# 获取商品信息
sku = GoodsSKU.objects.get(id=sku_id)
except GoodsSKU.DoesNotExist:
# from django.http import Http404
# raise Http404("商品不存在!")
return redirect(reverse("goods:index"))
# 获取类别
categorys = GoodsCategory.objects.all()
# 从订单中获取评论信息
sku_orders = sku.ordergoods_set.all().order_by('-create_time')[:30]
if sku_orders:
for sku_order in sku_orders:
sku_order.ctime = sku_order.create_time.strftime('%Y-%m-%d %H:%M:%S')
sku_order.username = sku_order.order.user.username
else:
sku_orders = []
# 获取最新推荐
new_skus = GoodsSKU.objects.filter(category=sku.category).order_by("-create_time")[:2]
# 获取其他规格的商品
goods_skus = sku.goods.goodssku_set.exclude(id=sku_id)
context = {
"categorys": categorys,
"sku": sku,
"orders": sku_orders,
"new_skus": new_skus,
"goods_skus": goods_skus
}
# 设置缓存
cache.set("detail_%s" % sku_id, context, 3600)
# 购物车数量
cart_num = self.get_cart_num(request)
# 浏览记录
# 如果是登录的用户
if request.user.is_authenticated():
redis_conn = get_redis_connection("default")
user_id = request.user.id
# 移除已经存在的本商品浏览记录
redis_conn.lrem("history_%s" % user_id, 0, sku_id)
# 添加新的浏览记录
redis_conn.lpush("history_%s" % user_id, sku_id)
# 只保存最多5条记录
redis_conn.ltrim("history_%s" % user_id, 0, 4)
context.update({"cart_num": cart_num})
return render(request, 'detail.html', context)
二、用户中心
在用户进入个人中心之前都需要先验证用户是否登录,在很多地方都会需要用到登录验证,比如下单、支付、填写地址。所以最好将验证登录作为一个可继承的 mixin 类,这样在其它需要登录验证的视图中就可以直接继承。
① 验证用户的登录状态
class LoginRequiredMixin(object):
"""验证用户的登录状态"""
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
② 用户中心
class UserInfoView(LoginRequiredMixin, View):
"""用户中心"""
def get(self, request):
user = request.user
try:
address = user.address_set.latest("create_time")
except Address.DoesNotExist:
# 如果地址信息不存在
address = None
# 从django_redis中拿到一个与redis的连接对象
redis_conn = get_redis_connection("default")
# 从redis中查询用户的历史记录信息
sku_ids = redis_conn.lrange("history_%s" % user.id, 0, 4)
# sku_ids = [5,6,3,9,1]
# 从数据库中查询商品的信息
# select * from goods_sku where id in ()
# skus = GoodsSKU.objects.filter(id__in=sku_ids)
skus = []
for sku_id in sku_ids: # [5,6,3,9,1]
sku = GoodsSKU.objects.get(id=sku_id)
skus.append(sku)
# 形成模板所用的变量,渲染模板
context = {
"address": address,
"skus": skus # [5,6,3,9,1]
}
return render(request, "user_center_info.html", context)