1.轮播图
轮播图没东西 因为之前涉及了model 所以直接使用ListModelMixin就好了 Serializer也是获得所有即可。
代码:
# models.py
class GoodsImage(models.Model):
"""
商品轮播图
"""
goods = models.ForeignKey(Goods, verbose_name=u'商品', related_name = 'images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='', verbose_name=u'图片', null=True, blank=True)
index = models.IntegerField(default=0, verbose_name=u'轮播顺序')
add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
class Meta:
verbose_name = u'商品图片'
verbose_name_plural = verbose_name
def __str__(self):
return self.goods.name
# views.py
from .models import Banner
from .serializers import BannerSerializer
class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
获取轮播图列表
"""
queryset = Banner.objects.all().order_by("index")
serializer_class = BannerSerializer
# serializers.py
from goods.models import Banner
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
# urls.py
from goods.views import BannerViewset
router.register('banners', BannerViewset, base_name='banners')
这样轮播图就完成了
2.新品功能开发;
因为新品是goods(model)中的一个字段名 所以只需要将过滤条件增加一个就可以了
# 之前写的那个fitlers.py 在fields中增加一个‘is_new’元素即可
# encoding:utf-8
import django_filters
from django.db.models import Q
from .models import Goods
class GoodsFilter(django_filters.rest_framework.FilterSet):
"""
商品的过滤类
"""
pricemin = django_filters.NumberFilter(field_name='shop_price', lookup_expr='gte', help_text="最低价格")
pricemax = django_filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
# 获取相应类别下的所有商品
top_category = django_filters.NumberFilter(method='top_category_filter')
# 这是全部匹配
name = django_filters.CharFilter(field_name='name')
# 这是部分匹配 不分大小写
# name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
def top_category_filter(self, queryset, name, value):
return queryset.filter(Q(category_id = value) | Q(category__parent_category_id = value) | Q(category__parent_category__parent_category_id = value))
class Meta:
model = Goods
# ------------------------------------------------------> 这里
fields = ['pricemin','pricemax', 'name', 'is_hot', 'is_new']
3. 商品分类显示
主页的这部分
这里面涉及了很多内容 多层级的1对多的关系
先做商品类型的展示,就是图片左下角的那些
class IndexCategorySerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
fields = "__all__"
首先先做品牌展示 利用商品类别来方向选择对应类别的品牌
在model中我们添加related_name参数,这样方便做反向选择
# models.py/class GoodsCategoryBrand
# Django2.0以上需要增加on_delete参数 针对外键
category = models.ForeignKey(GoodsCategory, related_name="brands", null=True, blank=True, verbose_name=u'商品类目', on_delete=models.CASCADE)
这样在goods_category中就可以反向拿到brand(品牌)了
然后我们在写一个brand的Serializer 然后嵌套到IndexSerializer中
这里有一个要明确 indexSerializer是包含上面截的整张图的所有信息。所以 相关的Serializer都会嵌套进去 统一返回给前端
# Serializers.py
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
class Meta:
model = GoodsCategory
fields = "__all__"
为什么不能直接用goods的Serializer。
goods中确实有一个外键指向我们的category。为什么不能反向取。
>因为商品选择哪个类别的时候,往往选择的是最小的类别。(第三类)
而不是直接从属于第一类。
获取商品:
外键指向的第三类。而我们要拿到第一类别的数据。直接使用goods的Serializer取不出来。
自定义商品(取相应类别的商品,使用自定义函数Serializer字段)
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
goods = serializers.SerializerMethodField()
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)
return goods_serializer.data
获取二类商品类别,利用之前做过的那个GategorySerializer2
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
goods = serializers.SerializerMethodField()
sub_cat = CategorySerializer2(many=True)
# 这是之前做的
class CategorySerializer2(serializers.ModelSerializer):
sub_cat = CategorySerializer3(many=True)
class Meta:
model = GoodsCategory
fields = "__all__"
最后搞右边的那7张图片
先去建model
class IndexAd(models.Model):
"""
首页类别标签右边展示的七个商品广告
"""
category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='category', verbose_name="商品类目")
goods = models.ForeignKey(Goods, on_delete=models.CASCADE, related_name='goods')
class Meta:
verbose_name = '首页广告'
verbose_name_plural = verbose_name
def __str__(self):
return self.goods.name
然后在IndexCategorySerializer中增加这些广告
from goods.models import IndexAd
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
goods = serializers.SerializerMethodField()
sub_cat = CategorySerializer2(many=True)
ad_goods = serializers.SerializerMethodField()
def get_ad_goods(self, obj):
goods_json = {}
ad_goods = IndexAd.objects.filter(category_id = obj.id)
if ad_goods:
goods_ins = ad_goods[0].goods
goods_json = GoodsSerializer(goods_ins, many=False).data
return goods_json
这时候输出到前端的img路径是不包含url地址的。 因为我们在Serializer中嵌套了serializer 并且还自定义了序列化方法。 这样的形式默认是不会加上url的 所以我们需要在嵌套的Serializer中加上context参数
def get_ad_goods(self, obj):
goods_json = {}
ad_goods = IndexAd.objects.filter(category_id = obj.id)
if ad_goods:
goods_ins = ad_goods[0].goods
# --------------------------------------------------------------> 这里
goods_json = GoodsSerializer(goods_ins, many=False, context={'request': self.context['request']}).data
return goods_json
这样输出到前端的图片路径就是包含URL域名的了。 帖完整的Serializer代码
from goods.models import Goods, GoodsCategory, GoodsImage, Banner, GoodsCategoryBrand, IndexAd
from django.db.models import Q
class IndexCategorySerializer(serializers.ModelSerializer):
brands = BrandSerializer(many=True)
goods = serializers.SerializerMethodField()
sub_cat = CategorySerializer2(many=True)
ad_goods = serializers.SerializerMethodField()
def get_ad_goods(self, obj):
goods_json = {}
ad_goods = IndexAd.objects.filter(category_id = obj.id)
if ad_goods:
goods_ins = ad_goods[0].goods
goods_json = GoodsSerializer(goods_ins, many=False, context={'request': self.context['request']}).data
return goods_json
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']})
return goods_serializer.data
class Meta:
model = GoodsCategory
fields = "__all__"
然后我们来写view
class IndexCategoryViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
首页商品分类数据
"""
# 限定了是否是用于导航 并且限定了两类商品(正式环境是不限定商品类型)
queryset = GoodsCategory.objects.filter(is_tab=True, name__in=["生鲜食品","酒水饮料"])
serializer_class = IndexCategorySerializer
urls.py:
#主页商品系列数据
router.register('indexgoods', IndexCategoryViewset, base_name='indexgoods')