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

【Vue+DRF生鲜电商】31.首页商品按分类显示推荐功能

admin2019年8月14日 13:52 Django | Html | JavaScript | Vue 1490人已围观

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

## 首页商品分类显示功能 这里面有多个一对多的关系: - 一级分类---品牌图片Brand - 一级分类---二级分类 - 一级分类---商品 在 apps/goods/models.py 中`GoodsCategoryBrand`添加分类的外键关联名 ```python class GoodsCategoryBrand(models.Model): """ 品牌 """ category = models.ForeignKey(GoodsCategory, null=True, blank=True, on_delete=models.CASCADE, verbose_name='商品类别', help_text='商品类别', related_name='brands') # ...... ``` `Goods`中也添加一个分类关联名 ```python class Goods(models.Model): """ 商品 """ category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='商品类别', help_text='商品类别', related_name='goods') # ...... ``` 方便之后从分类中通过关联名称直接取到品牌图片和商品。 ### IndexCategoryGoodsSerializer序列化首页分类商品 在 apps/goods/serializers.py 新建一个 `apps/goods/serializers.py`类,用于序列化一级分类,以及该分类下的品牌图片,二级分类,和子分类下的所有商品。 ```python from .models import Goods, GoodsCategory, GoodsImage, Banner, GoodsCategoryBrand # 品牌图片 class BrandsSerializer(serializers.ModelSerializer): class Meta: model = GoodsCategoryBrand fields = "__all__" # 首页分类商品序列化 class IndexCategoryGoodsSerializer(serializers.ModelSerializer): brands = BrandsSerializer(many=True) # 分类下的品牌图片 # goods = GoodsSerializer(many=True) # 不能这样用,因为现在需要的是一级分类,而大多数商品是放在三级分类中的,所以很多商品是取不到的,所以到自己查询一级分类子类别下的所有商品 goods = serializers.SerializerMethodField() sub_category = CategorySerializer2(many=True) # 序列化二级分类 def get_goods(self, obj): # 查询每级分类下的所有商品 all_goods = Goods.objects.filter(Q(category_id=obj.id) | Q(category__parent_category_id=obj.id) | Q(category__parent_category__parent_category_id=obj.id)) # 将查询的商品集进行序列化 goods_serializer = GoodsSerializer(all_goods, many=True) # 返回json对象 return goods_serializer.data class Meta: model = GoodsCategory fields = '__all__' ``` ### IndexCategoryGoodsViewSet首页分类及商品显示 apps/goods/views.py 添加`IndexCategoryGoodsViewSet`类,用于首页显示 ```python from .serializers import GoodsSerializer, CategorySerializer, ParentCategorySerializer, BannerSerializer, IndexCategoryGoodsSerializer class IndexCategoryGoodsViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ list: 首页分类、商品数据 """ queryset = GoodsCategory.objects.filter(category_type=1) serializer_class = IndexCategoryGoodsSerializer def get_queryset(self): # 随机取出几个分类 import random category_id_list = self.queryset.values_list('id', flat=True) selected_ids = random.sample(list(category_id_list), 3) qs = self.queryset.filter(id__in=selected_ids) return qs ``` 首先只获取一级分类,然后再随机选择其中3个显示在首页 ### 添加首页分类商品路由 修改 DjangoOnlineFreshSupermarket/urls.py 添加 ```python from goods.views import GoodsListView, GoodsListViewSet, CategoryViewSet, ParentCategoryViewSet, BannerViewSet, IndexCategoryGoodsViewSet router.register(r'indexgoods', IndexCategoryGoodsViewSet, base_name='indexgoods') # 首页分类及商品 ``` 现在访问 http://127.0.0.1:8000/indexgoods/?format=json 就可以看下序列化后的json格式数据 ![BLOG_20190814_135530_67](/media/blog/images/2019/08/BLOG_20190814_135530_67.png "博客图集BLOG_20190814_135530_67.png") 由于我们没有添加品牌的图片,所以值为空,之后再补充。 ### Vue首页分类商品接口联调 Vue中显示分类商品的组件在 src/views/index/series-list.vue ,组件创建时调用`this.getList()`方法 ```JavaScript getList() { queryCategorygoods() .then((response) => { //跳转到首页页response.body面 console.log('首页获取分类及商品数据'); console.log(response); this.list = response.data }) .catch(function (error) { console.log(error); }); } ``` 这时候会请求`queryCategorygoods()`函数,也就是访问接口 ```JavaScript //获取商品类别信息 export const queryCategorygoods = params => { return axios.get(`${local_host}/indexgoods/`) }; ``` 得到数据之后赋值给`this.list`进行遍历 这我先把 src/views/index/series-list.vue 的广告位注释掉了,否则数据循环可能会会报错 ```html <div class="series_pic"> 广告位 <!--router-link :to="'/app/home/productDetail/'+items.ad_goods.id" target=_blank> <img :src="items.ad_goods.goods_front_image" width="340" height="400"> </router-link--> </div> ``` 接下来访问 http://127.0.0.1:8080/#/app/home/index 就能看到这些数据了 ![BLOG_20190814_135521_91](/media/blog/images/2019/08/BLOG_20190814_135521_91.png "博客图集BLOG_20190814_135521_91.png") 按理说这些商品图片是显示不出来的,因为后端在序列化时,并没有加上域名。之后测试。 ![BLOG_20190814_135515_34](/media/blog/images/2019/08/BLOG_20190814_135515_34.png "博客图集BLOG_20190814_135515_34.png") ### 首页类别中的广告位和品牌图片 #### 首页类别广告模型 在 apps/goods/models.py 创建一个新的模型 ```python class IndexCategoryAd(models.Model): """ 首页广告 """ category = models.ForeignKey(GoodsCategory, null=True, blank=True, on_delete=models.CASCADE, verbose_name='商品类别', help_text='商品类别', related_name='ads') goods = models.ForeignKey(Goods, verbose_name='商品', help_text='商品', on_delete=models.CASCADE, related_name='ads') add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间') class Meta: verbose_name_plural = verbose_name = '首页类别广告' def __str__(self): return self.category ``` 添加完成后记得执行`makemigrations`和`migrate` #### 后台类别广告添加一些数据 修改 apps/goods/admin.py 注册广告的models ```python from .models import GoodsCategory, Goods, GoodsImage, IndexCategoryAd @admin.register(IndexCategoryAd) class IndexCategoryAdAdmin(admin.ModelAdmin): list_display = ['category', 'goods'] ``` 访问Django后台 http://127.0.0.1:8000/admin/goods/indexcategoryad/add/ 添加一些广告位商品,一定要添加到一级分类下 ![BLOG_20190814_135508_53](/media/blog/images/2019/08/BLOG_20190814_135508_53.png "博客图集BLOG_20190814_135508_53.png") #### 后台类别广告中category过滤 当选择商品类别时,会显示所有级别的类别,如果想只显示一级分类,修改 apps/goods/admin.py 中的`IndexCategoryAdAdmin` ```python @admin.register(IndexCategoryAd) class IndexCategoryAdAdmin(admin.ModelAdmin): list_display = ['category', 'goods'] def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == 'category': # 外键下拉框添加过滤 kwargs['queryset'] = GoodsCategory.objects.filter(category_type=1) return super(IndexCategoryAdAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) ``` ![BLOG_20190814_135503_52](/media/blog/images/2019/08/BLOG_20190814_135503_52.png "博客图集BLOG_20190814_135503_52.png") #### 序列化广告位商品 修改 apps/goods/serializers.py ```python # 首页分类商品序列化 class IndexCategoryGoodsSerializer(serializers.ModelSerializer): brands = BrandsSerializer(many=True) # 分类下的品牌图片 # goods = GoodsSerializer(many=True) # 不能这样用,因为现在需要的是一级分类,而大多数商品是放在三级分类中的,所以很多商品是取不到的,所以到自己查询一级分类子类别下的所有商品 goods = serializers.SerializerMethodField() sub_category = CategorySerializer2(many=True) # 序列化二级分类 ad_goods = serializers.SerializerMethodField() # 广告商品可能加了很多,取每个分类第一个 def get_ad_goods(self, obj): all_ads = obj.ads.all() if all_ads: ad = all_ads.first().goods # 获取到商品分类对应的商品 ad_serializer = GoodsSerializer(ad) # 序列化该广告商品 return ad_serializer.data else: # 在该分类没有广告商品时,必须要返回空字典,否则Vue中取obj.id会报错 return {} def get_goods(self, obj): # 查询每级分类下的所有商品 all_goods = Goods.objects.filter(Q(category_id=obj.id) | Q(category__parent_category_id=obj.id) | Q(category__parent_category__parent_category_id=obj.id)) # 将查询的商品集进行序列化 goods_serializer = GoodsSerializer(all_goods, many=True) # 返回json对象 return goods_serializer.data class Meta: model = GoodsCategory fields = '__all__' ``` 接下来访问 http://127.0.0.1:8000/indexgoods/?format=json 就可以显示广告商品的数据了 ![BLOG_20190814_135456_70](/media/blog/images/2019/08/BLOG_20190814_135456_70.png "博客图集BLOG_20190814_135456_70.png") #### 后台品牌图片增加一些数据 访问Django后台 http://127.0.0.1:8000/admin/goods/goodscategorybrand/ 随意添加一些数据到一级分类下 ![BLOG_20190814_135445_19](/media/blog/images/2019/08/BLOG_20190814_135445_19.png "博客图集BLOG_20190814_135445_19.png") 也可以按照首页类别广告的后台注册代码,对商品类别就行过滤。 #### Vue和广告商品联调 修改Vue主页组件 src/views/index/series-list.vue 将广告位取消注释 ```html <div class="series_pic"> <router-link :to="'/app/home/productDetail/'+items.ad_goods.id" target=_blank> <img :src="items.ad_goods.goods_front_image" width="340" height="400"> </router-link> </div> ``` ![BLOG_20190814_135436_36](/media/blog/images/2019/08/BLOG_20190814_135436_36.png "博客图集BLOG_20190814_135436_36.png") 由于只添加了部分数据,所有很多都没有显示完整。 ### 序列化嵌套序列化商品图片url加上域名 示例序列化的结果:商品图片`goods_front_image: "/media/upload/goods_init/images/1_P_1449024889889.jpg",`没有加上域名 将 proxy.js 进行修改,改为一个不存在的地址,修改了需要重启服务器,最好清除浏览器缓存货隐身模式下测试 ```JavaScript module.exports = { "/": "http://myserver.com:8001" //如果部署服务器,需修改为服务器的域名 //"/": "http://127.0.0.1:8000" }; ``` 现在访问就出现破图了 ![BLOG_20190814_135428_21](/media/blog/images/2019/08/BLOG_20190814_135428_21.png "博客图集BLOG_20190814_135428_21.png") > 当我们的url没有域名,也就是类似`"/media/upload/goods_init/images/1_P_1449024889889.jpg"`的地址,就会自动加上 proxy.js 中配置的域名,所以之前能够正常显示。 在 apps/goods/serializers.py 的`IndexCategoryGoodsSerializer`中,也就是Serializer调用另一个Serializer是不会自动加上域名的,如果要加上域名,需要在嵌套的Serializer中添加一个参数`context={'request': self.context['request']}` ```python # 首页分类商品序列化 class IndexCategoryGoodsSerializer(serializers.ModelSerializer): brands = BrandsSerializer(many=True) # 分类下的品牌图片 # goods = GoodsSerializer(many=True) # 不能这样用,因为现在需要的是一级分类,而大多数商品是放在三级分类中的,所以很多商品是取不到的,所以到自己查询一级分类子类别下的所有商品 goods = serializers.SerializerMethodField() sub_category = CategorySerializer2(many=True) # 序列化二级分类 ad_goods = serializers.SerializerMethodField() # 广告商品可能加了很多,取每个分类第一个 def get_ad_goods(self, obj): all_ads = obj.ads.all() if all_ads: ad = all_ads.first().goods # 获取到商品分类对应的商品 ad_serializer = GoodsSerializer(ad, context={'request': self.context['request']}) # 序列化该广告商品,嵌套的序列化类中添加context参数,可在序列化时添加域名 return ad_serializer.data else: # 在该分类没有广告商品时,必须要返回空字典,否则Vue中取obj.id会报错 return {} def get_goods(self, obj): # 查询每级分类下的所有商品 all_goods = Goods.objects.filter(Q(category_id=obj.id) | Q(category__parent_category_id=obj.id) | Q(category__parent_category__parent_category_id=obj.id)) # 将查询的商品集进行序列化 goods_serializer = GoodsSerializer(all_goods, many=True, context={'request': self.context['request']}) # 返回json对象 return goods_serializer.data class Meta: model = GoodsCategory fields = '__all__' ``` 现在广告商品和分类商品的图片url已正常添加域名了 ![BLOG_20190814_135419_65](/media/blog/images/2019/08/BLOG_20190814_135419_65.png "博客图集BLOG_20190814_135419_65.png") ![BLOG_20190814_135414_15](/media/blog/images/2019/08/BLOG_20190814_135414_15.png "博客图集BLOG_20190814_135414_15.png") 加上这个`context`参数后,刷新页面,图片就正常显示了 ![BLOG_20190814_135409_15](/media/blog/images/2019/08/BLOG_20190814_135409_15.png "博客图集BLOG_20190814_135409_15.png")

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行2076天
  • 系统信息:Linux
  • 后台程序:Python: 3.8.10
  • 网站框架:Django: 3.2.6
  • 文章统计:256 篇
  • 文章评论:60 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站