本文继续完成项目的内容,下面完成的是用户浏览记录。
1.用户浏览记录
在本项目中,当用户每次浏览商品详情时,会向后台发送请求,此时可携带商品ID,然后在Redis数据库中进行存储信息,此时可缓存用户ID和浏览商品的ID,并以浏览商品时间先后顺序进行排序,就可以实现存储用户浏览历史记录。
此外,我们可以使用Redis数据库的列表来存储商品浏览记录,以用户ID 为key,分别存入商品信息,添加商品历史浏览记录时,用户最新浏览的商品的id从列表左侧默认插入。
首先,创建一个超级管理员,在goods中的每一个应用里的admin.py中注册模型,在后台显示字段;
from django.contrib import admin
from .models import *
# Register your models here.
class GoodsSKUBeanAdmin(admin.ModelAdmin):
list_display = ['id','name','price','unit','surplus','sale_count','image','status']
list_display_links = ['name']
list_editable = ['price','unit','surplus','sale_count']
class GoodsKindBeanAdmin(admin.ModelAdmin):
list_display = ['id','name','logo','image']
class GoodsSPUBeanAdmin(admin.ModelAdmin):
list_display = ['id','name','detail']
admin.site.register(GoodsSKUBean,GoodsSKUBeanAdmin)
admin.site.register(GoodsKindBean,GoodsKindBeanAdmin)
admin.site.register(GoodsSPUBean,GoodsSPUBeanAdmin)
在后台添加商品种类,种类logo是一张‘雪碧图’,因此可以切换class来实现图标的定位;
接下来,要获取浏览商品记录,则需要用户访问商品详情后,获取相应的GoodSKUBean值(如name、price等)即可,在user/views.py中的UserInfoView类视图中,获取浏览商品记录,并传递给模板;
class UserInfoView(View):
def get(self,request):
user = request.user
try:
default_address = AddressBean.objects.get(user=user,is_default=1,is_delete=0)
except:
default_address = None
# 获取最近浏览的商品
# 获取连接对象 把用户浏览记录放入到redis中
conn = get_redis_connection("default")
# 构造存储浏览记录的key
historykey = f"history_{user.id}"
# 根据key获取最新的5条skuid列表
skuids = conn.lrange(historykey,0,4)
# 根据每一个skuid查询相应的产品信息
goodsSkuList = []
for skuid in skuids:
goodsSku = GoodsSKUBean.objects.get(id=skuid)
goodsSkuList.append(goodsSku)
return render(request,'user_center_info.html',
{'page':'info',
'default_address':default_address,
'goodsSkuList':goodsSkuList
})
再在用户中心的个人信息下的模板文件 user_center_info.html 中进行页面渲染,显示数据;
{% if goodsSkuList %}
<h3 class="common_title2">最近浏览</h3>
<div class="has_view_list">
<ul class="goods_type_list clearfix">
{% for goodsSku in goodsSkuList %}
<li>
<a href="/detail/{{ goodsSku.id }}"><img src="/media/{{ goodsSku.image }}"></a>
<h4><a href="/detail/{{ goodsSku.id }}">{{ goodsSku.name }}</a></h4>
<div class="operate">
<span class="prize">{{ goodsSku.price }}</span>
<span class="unit">{{ goodsSku.price }}{{ goodsSku.unit }}</span>
<a href="#" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
效果如下:
若要添加用户访问商品详情页面的浏览记录,则需要让用户中心的个人信息显示出最近浏览商品的信息,这里我们需要在goods中实现访问商品详情页,在goods/views.py文件中创建DetailView类视图;
class DetailView(View):
def get(self,request,skuId):
user = request.user
# 详情页的数据:登录用户和匿名用户都是可以访问的,但是只有登录用户需要取记录浏览记录
# 登录用户浏览记录的缓存
if user.is_authenticated:
# 缓存用户的浏览记录
# 获取连接对象
conn = get_redis_connection("default")
# 构造存储浏览记录的key
historykey = f"history_{user.id}"
# 移除对应的skuId在缓存中的记录
conn.lrem(historykey,0,skuId)
# 将skuId重新添加到用户浏览记录缓存中
conn.lpush(historykey,skuId)
# 只保存记录中最新的五条数据-截取
conn.ltrim(historykey,0,4)
return render(request,'detail.html')
设置分路由;
url(r'^detail/(?P<skuId>\d+)',DetailView.as_view(),name='detail'),
主路由中的设置;
url(r'^goods/', include('apps.goods.urls')),
访问详情页即可在用户中心处的个人信息中查看浏览记录;
2.上下文处理器
这里我们补充一个知识点,上下文处理器是可以返回一些数据,在局部中可以用,在全局模板中也可以使用。比如登录后的用户信息,在很多界面中都需要使用,那么我们可以放在上下文处理器中,就不需要在每个视图函数中都返回这个对象。
上下文处理器的存放位置
可以根据上下文处理器是属于哪个app的,然后在这个app中创建一个文件用于存储上下文处理器。比如context_processors.py。或者是你也可以专门创建一个Python包,用来存储所有的上下文处理器。
上下文处理器的使用
在定义的上下文处理器文件中,定义一个函数,这个函数只有一个request参数。这个函数中处理完自己的逻辑后,把需要返回给模板的数据,通过字典的形式返回。如果不需要返回任何数据,也必须返回一个空的字典。
案例:
自定义用户登录注册系统时,登录后将用户名放入session中,但是需要在每个页面获取用户的姓名,如果在每一个视图里面写获取逻辑会很麻烦,不利于代码的维护,可以设置全局上下文,获取session中的用户名的值。
在user应用下建立context_processors.py,并在settings.py中引入这个上下文变量;
def getUser(request):
user_name = request.session.get('user_name',None)
return {'user_name': user_name}
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'user.context_processors.getUser'
],
到此,在所有模板中都可以访问这个变量。