您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django

【Vue+DRF生鲜电商】17.DRF实现商品详情及热卖商品接口,Vue中显示商品详情和热卖

admin2019年5月30日 14:46 Django | Vue 221人已围观

Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。

## viewsets实现商品详情页接口 ### 添加商品详情类继承RetrieveModelMixin 在 goods/views.py 中显示商品列表的ViewSet为` GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet)` ,它继承了`mixins.ListModelMixin`之后,是显示商品的列表页,如果要显示商品的详情,只需要再继承`mixins.RetrieveModelMixin`,就可以了,代码如下: ```python class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): """ 显示商品列表,分页、过滤、搜索、排序 显示商品详情 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter # authentication_classes = (TokenAuthentication, ) # 只在本视图中验证Token search_fields = ('name', 'goods_desc', 'category__name') # 搜索字段 ordering_fields = ('click_num', 'sold_num', 'shop_price') # 排序 ``` 在商品详情页有商品的轮播图,是关联的另一个模型`GoodsImage(models.Model)`,商品有一个外键`images`指向该模型。 ```python class GoodsImage(models.Model): """ 商品图片 """ goods = models.ForeignKey(Goods, verbose_name='商品', help_text='商品', on_delete=models.CASCADE, related_name='images') image = models.ImageField(upload_to='goods/images/', verbose_name='图片', help_text='图片') add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间') class Meta: verbose_name_plural = verbose_name = '商品图片' def __str__(self): return self.goods.name ``` 还需要序列化商品轮播图,修改 goods/serializers.py ,添加商品轮播图序列化类 ```python from .models import Goods, GoodsCategory, GoodsImage # 商品图片序列化 class GoodsImageSerializer(serializers.ModelSerializer): class Meta: model = GoodsImage fields = ['image'] # 需要的字段只需要image class GoodsSerializer(serializers.ModelSerializer): category = CategorySerializer() # 自定义字段覆盖原有的字段,实例化 images = GoodsImageSerializer(many=True) # 字段名和外键名称一样,商品轮播图,需要加many=True,因为一个商品有多个图片 class Meta: model = Goods fields = '__all__' ``` 访问后台 http://127.0.0.1:8000/goods/ ![BLOG_20190530_155352_25](/media/blog/images/2019/05/BLOG_20190530_155352_25.png "博客图集BLOG_20190530_155352_25.png") 可以看到每个商品的轮播图字段都已经显示了,整个轮播图url都能拼凑好,指定商品id,可以看到该商品的详细信息,例如 http://127.0.0.1:8000/goods/105/ ![BLOG_20190530_155344_89](/media/blog/images/2019/05/BLOG_20190530_155344_89.png "博客图集BLOG_20190530_155344_89.png") ### Vue显示商品详情分析 显示商品详情的组件为 src/views/productDetail/productDetail.vue ```JavaScript created() { this.productId = this.$route.params.productId; var productId = this.productId; // .... } ``` 从这可以获取到点击商品传递过来的商品id,然后调用`getGoodsDetail` ```JavaScript getDetails() { // 请求商品详情 getGoodsDetail(this.productId) .then((response) => { //console.log(response.data); this.proDetail = response.data; this.curShow = this.proDetail.images[0]; }).catch(function (error) { console.log(error); }); }, ``` 在 src/api/api.js 中,定义了获取商品详情的url ```js //获取商品列表 export const getGoods = params => { return axios.get(`${local_host}/goods/`, {params: params}) }; //商品详情 export const getGoodsDetail = goodId => { return axios.get(`${local_host}/goods/${goodId}` + '/') }; ``` 访问某个商品详情 http://127.0.0.1:8080/#/app/home/productDetail/105 ![BLOG_20190530_155332_59](/media/blog/images/2019/05/BLOG_20190530_155332_59.png "博客图集BLOG_20190530_155332_59.png") 顶部的面包屑只显示该商品的分类,定义在 src/views/productDetail/current-loc/current-loc.vue 中 ```html <div class="menus"> <a href="">首页</a> <code>&gt;</code> <!--<a href="">{{curLoc.category.name}}</a>--> <router-link :to="{name: 'list', params:{id: curLoc.category.id}}">{{curLoc.category.name}}</router-link> <code>&gt;</code> {{curLoc.name}} </div> ``` 商品详情就可以正常显示了,如果出现下面错误,需要修改代理。 ### Error occured while trying to proxy to:xxx ![BLOG_20190530_155324_47](/media/blog/images/2019/05/BLOG_20190530_155324_47.png "博客图集BLOG_20190530_155324_47.png") ![BLOG_20190530_155318_47](/media/blog/images/2019/05/BLOG_20190530_155318_47.png "博客图集BLOG_20190530_155318_47.png") ![BLOG_20190530_155312_41](/media/blog/images/2019/05/BLOG_20190530_155312_41.png "博客图集BLOG_20190530_155312_41.png") 如果直接访问出错的图片 http://127.0.0.1:8080/media/upload/goods_init/images/2_20170719161405_249.jpg 会提示 ``` Error occured while trying to proxy to: 127.0.0.1:8080/media/upload/goods_init/images/2_20170719161405_249.jpg ``` 修改方法,将Vue项目根目录中 proxy.js 进行修改,配置为本地服务器的地址 ```JavaScript module.exports = { // "/": "http://myserver.com:8001" //如果部署服务器,需修改为服务器的域名 "/": "http://127.0.0.1:8000" }; ``` 关闭npm服务后重启,访问呢就正常了 ![BLOG_20190530_155304_74](/media/blog/images/2019/05/BLOG_20190530_155304_74.png "博客图集BLOG_20190530_155304_74.png") ### Django后台轮播图一对多关系管理 修改 goods/admin.py 商品详情轮播图显示到同一页 ```python from .models import GoodsCategory, Goods, GoodsImage class GoodsImageInline(admin.TabularInline): model = GoodsImage @admin.register(Goods) class GoodsAdmin(admin.ModelAdmin): list_display = ['name'] inlines = [ GoodsImageInline ] ``` 访问 http://127.0.0.1:8000/admin/goods/goods/105/change/ 可以对商品图片进行管理 ![BLOG_20190530_155253_29](/media/blog/images/2019/05/BLOG_20190530_155253_29.png "博客图集BLOG_20190530_155253_29.png") 这可以对商品轮播图进行修改。 ## 热卖商品接口实现 ### DRF中增加is_hot过滤商品 在商品的model中定义了一个`is_hot`字段,用于指定商品是否热销 ```python class Goods(models.Model): # 。。。 is_hot = models.BooleanField(default=False, verbose_name='是否热销', help_text='是否热销') ``` 有了这个字段之后,要获取热销产品,只需要添加这个字段的过滤,修改 apps/goods/filters.py 的`GoodsFilter(filters.FilterSet)` ```python class GoodsFilter(filters.FilterSet): """ 商品的过滤类 """ name = filters.CharFilter(field_name='name', lookup_expr='contains') # 包含关系,模糊匹配 goods_desc = filters.CharFilter(field_name='name', lookup_expr='contains') min_price = filters.NumberFilter(field_name="shop_price", lookup_expr='gte') # 自定义字段 max_price = filters.NumberFilter(field_name="shop_price", lookup_expr='lte') top_category = filters.NumberFilter(method='top_category_filter', field_name='category_id', lookup_expr='=') # 自定义过滤,过滤某个一级分类 def top_category_filter(self, queryset, field_name, value): """ 自定义过滤内容 这儿是传递一个分类的id,在已有商品查询集基础上获取分类id,一级一级往上找,直到将三级类别找完 :param queryset: :param field_name: :param value: 需要过滤的值 :return: """ queryset = queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q(category__parent_category__parent_category_id=value)) return queryset class Meta: model = Goods fields = ['name', 'goods_desc', 'min_price', 'max_price', 'is_hot'] ``` 在`fields`中添加`is_hot`字段 访问 http://127.0.0.1:8000/goods/ 在过滤器中就可以看到“是否热销”过滤了 ![BLOG_20190530_155240_23](/media/blog/images/2019/05/BLOG_20190530_155240_23.png "博客图集BLOG_20190530_155240_23.png") 将是否热销选择“是”,此时链接跳转到 http://127.0.0.1:8000/goods/?name=&goods_desc=&min_price=&max_price=&is_hot=true&top_category= ![BLOG_20190530_155215_62](/media/blog/images/2019/05/BLOG_20190530_155215_62.png "博客图集BLOG_20190530_155215_62.png") 但是没有结果,因为数据库中没有勾选热销的商品,进入Goods数据库,选择几个商品勾选 ```python >>> from goods.models import Goods >>> Goods.objects.filter(is_hot=True) <QuerySet []> # 勾选热销 >>> Goods.objects.filter(id__lte=110) <QuerySet [<Goods: 新鲜水果甜蜜香脆单果约800克>, <Goods: 田然牛肉大黄瓜条生鲜牛肉冷冻真空黄牛>, <Goods: 酣畅家庭菲力牛排10片澳洲生鲜牛肉团购套餐>, <Goods: 日本蒜蓉粉丝扇贝270克6只装>, <Goods: 内蒙新鲜牛肉1斤清真生鲜牛肉火锅食材>, <Goods: 乌拉圭进口牛肉卷特级肥牛卷>]> >>> Goods.objects.filter(id__lte=110).update(is_hot=True) 6 >>> Goods.objects.filter(is_hot=True) <QuerySet [<Goods: 新鲜水果甜蜜香脆单果约800克>, <Goods: 田然牛肉大黄瓜条生鲜牛肉冷冻真空黄牛>, <Goods: 酣畅家庭菲力牛排10片澳洲生鲜牛肉团购套餐>, <Goods: 日本蒜蓉粉丝扇贝270克6只装>, <Goods: 内蒙新鲜牛肉1斤清真生鲜牛肉火锅食材>, <Goods: 乌拉圭进口牛肉卷特级肥牛卷>]> ``` 现在刷新 http://127.0.0.1:8000/goods/?name=&goods_desc=&min_price=&max_price=&is_hot=true&top_category= 就可以看到内容 ![BLOG_20190530_155204_90](/media/blog/images/2019/05/BLOG_20190530_155204_90.png "博客图集BLOG_20190530_155204_90.png") 数量也是数据库中改变的数量。 ### Vue显示热销商品 热卖商品组件为 src/views/productDetail/hotSales.vue ![BLOG_20190530_155157_72](/media/blog/images/2019/05/BLOG_20190530_155157_72.png "博客图集BLOG_20190530_155157_72.png") ```JavaScript getHotSales() { //请求热卖商品 getGoods({ is_hot: true }) .then((response) => { //console.log(response.data) this.hotProduct = response.data.results; }).catch(function (error) { console.log(error); }); } ``` 这个也就是请求商品过滤`is_hot: true`的商品。

很赞哦! (0)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行586天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.9
  • 文章统计:222 篇
  • 文章评论:39 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 微信公众号:扫描二维码,关注我们
返回
顶部
标题 换行 登录
网站