第五课 Vue+Django rest framework生鲜商品类别数据和vue展示
文章目录
第一节 django view实现商品分类数据
1.1 categorys Api接口实现
- goods下views.py下写一个CategoryViewSet
from goods.serializer import GoodsSerializer, GoodsCategorySerializer
from .models import Goods, GoodsCategory
class CategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
list :
商品分类列表数据
"""
queryset = GoodsCategory.objects.all()
serializer_class = GoodsCategorySerializer
- Serializer.py实现GoodsCategorySerializer
class GoodsCategorySerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
fields = "__all__"
- 配置url.py
from goods.views import GoodsListViewset, CategoryViewSet
router.register(r'categorys', CategoryViewSet, basename="categorys")
- 运行,访问api。看下能否获取全部数据。
python manage.py runserver
http://127.0.0.1:8000/categorys/
1.2 categorys Api查询需要数据
- 如果要查询某一层级分类的数据, 修改CategoryViewSet
class CategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
list :
商品分类列表数据
"""
# queryset = GoodsCategory.objects.all()
queryset = GoodsCategory.objects.filter(category_type=1)
serializer_class = GoodsCategorySerializer
- **如何通过一类分类拿到二类分类的数据呢?并通过二类分类拿到三类分类数据?**记得我们model中有个字段。related_name="sub_cat"就是我们拿到下级数据的关键。一类对象.sub_cat就可以把下级数据取出来。
parent_category = models.ForeignKey("self", null=True, blank=True, verbose_name="父类目级别", help_text="父目录", related_name="sub_cat", on_delete=models.CASCADE)
- 修改Serializer.py实现上图的层级嵌套数据输出。这里下级多个必须加上many=True,防止报错。
class GoodsCategorySerializer3(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
fields = "__all__"
class GoodsCategorySerializer2(serializers.ModelSerializer):
sub_cat = GoodsCategorySerializer3(many=True)
class Meta:
model = GoodsCategory
fields = "__all__"
class GoodsCategorySerializer(serializers.ModelSerializer):
sub_cat = GoodsCategorySerializer2(many=True)
class Meta:
model = GoodsCategory
fields = "__all__"
- 这里获取某个具体分类下的具体商品也不需要我们重新定义视图函数和路由。直接在views.py下CategoryViewSet,多继承一个mixins.RetrieveModelMixin即可, 它内部帮我们已经实现了。
class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
list :
商品分类列表数据
"""
# queryset = GoodsCategory.objects.all()
queryset = GoodsCategory.objects.filter(category_type=1)
serializer_class = GoodsCategorySerializer
- 到数据库中查看category_type=1的category的id。直接访问可以看到查询出的数据即可:http://127.0.0.1:8000/categorys/57/
1.3 categorys Api和Vue接口调试
- 前端category在MxShop\online-store\src\views\head\head.vue中定义。
- 通过getMenu调用\MxShop\online-store\src\api\api.js中的函数getCategory。
- 本项目所有与drf后台交互的api接口全定义在\MxShop\online-store\src\api\api.js文件中。
- 源码中实际上从线上的环境中获取的。let host = ‘http://shop.projectsedu.com’;
- 如果要调试。可以重新给个变量,调试哪个接口就给它替换就行。let localhost = ‘http://127.0.0.1:8000’;
- 重启后台和前台项目。发现没有数据填充。报错跨域访问的问题。跨端口了实际上跨域了。
- 可以通过前段代理解决
- 也可以通过服务器的设置解决
Access to XMLHttpRequest at 'http://127.0.0.1:8000/categorys/' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 设置drf的跨域问题。到github查一下django cors headers。找到解决方案。settings.py中配置
- python -m pip install django-cors-headers
# 1. 注册
INSTALLED_APPS = [
...
'corsheaders',
...
]
# 2. 'corsheaders.middleware.CorsMiddleware'要尽量放在前面
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
# 3. CORS_ORIGIN_ALLOW_ALL=True 默认为false的
CORS_ORIGIN_ALLOW_ALL=True
-
重新刷新页面,获取数据正常。
-
http://127.0.0.1:8000/xadmin 到后台管理系统取喜欢的一级商品分类作为导航。
-
刷新前端页面,导航数据就可以但看到了。
第二节 django view实现商品列表页数据
2.1 商品列表页接口适配
- 修改后台页面中views.py中的类GoodsPagination。page_query_param = ‘page’
- MxShop\online-store\src\views\list\list.vue中展示函数。getListData
- 这里我们需要找到一级分类下所有二级分类,以及二级分类所有的商品。这里可以用filter自定义自己方法来写自己过滤逻辑。
from django_filters import rest_framework as filters
from .models import Goods
from django.db.models import Q
class GoodsFilter(filters.FilterSet):
"""
商品的过滤类
"""
pricemin = filters.NumberFilter(field_name="shop_price", lookup_expr='gte')
pricemax = filters.NumberFilter(field_name="shop_price", lookup_expr='lte')
# 模糊查询 忽略大小写icontains
# name = filters.CharFilter(field_name="name", lookup_expr='icontains')
top_category = filters.NumberFilter(method="top_category_filter")
# 这是三个参数是默认传递进来的queryset, name, value
def top_category_filter(self, queryset, name, value):
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 = ['pricemin', 'pricemax']
- views.py字段适配GoodsListViewset
class GoodsListViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
商品列表页,分页,搜索,过滤,排序
"""
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = GoodsPagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_class = GoodsFilter
# 查询和排序这里可以加一些正则的语法
search_fields = ['name', 'goods_brief', 'goods_desc']
ordering_fields = ['sold_num', 'shop_price']
# filterset_fields = ['name', 'shop_price']
- 刷新前端页面,测试。价格排序,搜索,价格区间,一类下的商品。