(项目)生鲜超市(七)
程序员文章站
2022-06-24 14:21:55
八、商品详情页功能 1、viewsets实现商品详情页接口 商品的轮播图是一个外键,序列化的时候需要用嵌套的方式来实现: 商品详情页面只需要在商品列表页的接口中继承mixins.RetrieveModelMixin就可以了: 现在就可以获取到某一个商品的详细数据了: 2、热卖商品接口实现 只需要在g ......
八、商品详情页功能
1、viewsets实现商品详情页接口
商品的轮播图是一个外键,序列化的时候需要用嵌套的方式来实现:
1 class goodsimageserializer(serializers.modelserializer): 2 """商品轮播图""" 3 4 class meta: 5 model = goodsimage 6 fields = ('image',) 7 8 9 class goodsserializer(serializers.modelserializer): 10 # 覆盖外键字段 11 category = categoryserializer() 12 13 # images是设置的related_name="images",把轮播图嵌套进来 14 images = goodsimageserializer(many=true) 15 16 class meta: 17 model = goods 18 fields = '__all__'
商品详情页面只需要在商品列表页的接口中继承mixins.retrievemodelmixin就可以了:
1 class goodslistviewset(mixins.listmodelmixin, mixins.retrievemodelmixin, viewsets.genericviewset): 2 """商品列表页面""" 3 4 pagination_class = goodspagination 5 queryset = goods.objects.all().order_by('id') # 必须定义一个默认的排序,否则会报错 6 serializer_class = goodsserializer 7 filter_backends = (djangofilterbackend, filters.searchfilter, filters.orderingfilter) 8 9 # 自定义过滤类 10 filter_class = goodsfilter 11 12 # 搜索,=name表示精确搜索,也可以使用正则 13 search_fields = ('name', 'goods_brief', 'goods_desc') 14 15 # 排序 16 ordering_fields = ('sold_num', 'shop_price')
现在就可以获取到某一个商品的详细数据了:
2、热卖商品接口实现
只需要在goods/filter.py中加上is_hot的过滤条件即可:
1 class goodsfilter(django_filters.rest_framework.filterset): 2 """商品过滤""" 3 4 # name是要过滤的字段,lookup是执行的行为 5 pricemin = django_filters.numberfilter(field_name="shop_price", lookup_expr='gte') 6 pricemax = django_filters.numberfilter(field_name="shop_price", lookup_expr='lte') 7 top_category = django_filters.numberfilter(field_name="category", method='top_category_filter') 8 9 def top_category_filter(self, queryset, name, value): 10 # 不管当前点击的是一级分类二级分类还是三级分类,都能找到 11 return queryset.filter(q(category_id=value) | q(category__parent_category_id=value) | q( 12 category__parent_category__parent_category_id=value)) 13 14 class meta: 15 model = goods 16 fields = ['pricemin', 'pricemax', 'is_hot']
然后在后台中将商品的是否热销选为true,现在点开商品详情,最下面有热卖商品就会显示出来:
3、用户收藏接口
在user_operation下新建serializers.py文件,序列化用户收藏model的字段:
1 from rest_framework import serializers 2 from rest_framework.validators import uniquetogethervalidator 3 4 from .models import userfav 5 6 7 class userfavserializer(serializers.modelserializer): 8 # 获取当前登录的用户 9 user = serializers.hiddenfield(default=serializers.currentuserdefault()) 10 11 class meta: 12 # validate实现唯一联合,一个商品只能收藏一次 13 validators = [ 14 uniquetogethervalidator( 15 queryset=userfav.objects.all(), 16 fields=('user', 'goods'), 17 # message的信息可以自定义 18 message="已收藏" 19 ) 20 ] 21 model = userfav 22 # 收藏的时候需要返回商品的id,因为取消收藏的时候必须知道商品的id是多少 23 fields = ('user', 'goods', 'id')
然后在views.py中编写用户收藏的接口,收藏需要继承createmodelmixin(添加收藏),destroymodelmixin(删除收藏),listmodelmixin(获取已收藏的商品列表),retrievemodelmixin(用于查询该商品是否被收藏):
1 from rest_framework import mixins, viewsets 2 3 from .serializers import userfavserializer 4 from .models import userfav 5 6 class userfavviewset(mixins.listmodelmixin, mixins.createmodelmixin, mixins.destroymodelmixin, 7 mixins.retrievemodelmixin, viewsets.genericviewset): 8 """用户收藏""" 9 10 queryset = userfav.objects.all() 11 serializer_class = userfavserializer
注册url:
1 router.register(r'userfavs', userfavviewset, base_name='userfavs') # 用户收藏
然后测试该接口,收藏三个商品,查看已收藏列表:
重复收藏商品会提示已收藏:
4、drf的权限验证
在utils下新建permissions.py,这个官网有实例,直接复制过来即可,把其中的owner改为user即可:
1 from rest_framework import permissions 2 3 4 class isownerorreadonly(permissions.basepermission): 5 """ 6 object-level permission to only allow owners of an object to edit it. 7 assumes the model instance has an `owner` attribute. 8 """ 9 10 def has_object_permission(self, request, view, obj): 11 # read permissions are allowed to any request, 12 # so we'll always allow get, head or options requests. 13 if request.method in permissions.safe_methods: 14 return true 15 16 # instance must have an attribute named `owner`. 17 # obj相当于数据库中的model,这里要把owner改为我们数据库中的user 18 return obj.user == request.user
在用户收藏接口中完善权限,收藏只有登录用户才能收藏且必须是当前登录用户,用户只能获取到自己收藏的列表,不能获取全部:
1 class userfavviewset(mixins.listmodelmixin, mixins.createmodelmixin, mixins.destroymodelmixin, 2 mixins.retrievemodelmixin, viewsets.genericviewset): 3 """用户收藏""" 4 5 serializer_class = userfavserializer 6 7 # permission是权限验证 isauthenticated必须登录用户 isownerorreadonly必须是当前登录的用户 8 permission_classes = (isauthenticated, isownerorreadonly) 9 10 # authentication是用户认证 11 authentication_classes = (jsonwebtokenauthentication, sessionauthentication) 12 13 # 搜索的字段 14 lookup_field = 'goods_id' 15 16 # 只能查看当前登录用户的收藏,不会获取所有用户的收藏 17 def get_queryset(self): 18 return userfav.objects.filter(user=self.request.user)
- jsonwebtokenauthentication认证不应该全局配置,因为用户获取商品信息或者其它页面的时候并不需要此认证,所以这个认证只要局部中添加就可以
- 删除settings中的rest_framework_jwt.authentication.jsonwebtokenauthentication
5、vue和用户收藏接口联调
修改vue前端代码中的host:
1 //收藏 2 export const addfav = params => { return axios.post(`${host}/userfavs/`, params) } 3 4 //取消收藏 5 export const delfav = goodsid => { return axios.delete(`${host}/userfavs/`+goodsid+'/') } 6 7 export const getallfavs = () => { return axios.get(`${host}/userfavs/`) } 8 9 //判断是否收藏 10 export const getfav = goodsid => { return axios.get(`${host}/userfavs/`+goodsid+'/') }
上一篇: 搞笑熊孩子,将来一定有出息
下一篇: Python头脑风暴1