欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(项目)生鲜超市(七)

程序员文章站 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+'/') }

(项目)生鲜超市(七)