• 【Vue+DRF 生鲜电商】商品列表页(三)


    1. APIView 实现商品列表页

    安装依赖:

    pip install coreapi    # drf的文档支持
    pip install django-guardian   #  drf对象级别的权限支持
    

    1、MxShop/urls.py

    from django.urls import path, include, re_path
    from django.views.static import serve
    from rest_framework.documentation import include_docs_urls
    
    urlpatterns = [
        # path('admin/', admin.site.urls),
    
        path('xadmin/', xadmin.site.urls),
        path('ueditor/', include('DjangoUeditor.urls')),
        path('media/<path:path>', serve, {'document_root': MEDIA_ROOT}),
    
        # drf 文档
        path('docs', include_docs_urls(title='hubery')),
        path('api-auth/', include('rest_framework.urls')),
    ]
    

    2、新建 goods/serializers.py,序列化商品数据:

    from rest_framework import serializers
    
    class GoodsSerializer(serializers.Serializer):
        """
        商品
        """
        name = serializers.CharField(required=True, max_length=100)
        click_num = serializers.IntegerField(default=0)
        goods_front_image = serializers.ImageField()
    
    # 也可以使用
    # class CategorySerializer(serializers.ModelSerializer):
    #     """
    #     分类
    #     """
    
    #     class Meta:
    #         model = GoodsCategory     # 指定模型
    #         fields = '__all__'    # 所以字段
    

    serializers.ModelSerializer 类似于 Django ModelForm 可以指定模型。

    2、goods/views.py

    from rest_framework.response import Response
    from rest_framework.views import APIView
    
    
    class GoodsListView(APIView):
        """
        商品列表
        """
    
        def get(self, request, format=None):
            goods = Goods.objects.all()
            goods_serilizer = GoodsSerializer(goods, many=True)
            return Response(goods_serilizer.data)
    

    APIView 需要自己实现 get、post 方法来处理请求。

    3、MxShop/urls.py 配置商品列表路由:

    from django.urls import path, include, re_path
    from django.views.static import serve
    
    from goods.views import GoodsListView
    
    urlpatterns = [
    
        path('goods/', GoodsListView.as_view(), name='goods'),
    ]
    

    运行项目,访问:http://127.0.0.1:8000/goods 查看商品列表页数据。

    1.1 处理外键字段

    通过上述方式处理,查询到的商品数据,分类 category 外键字段的数据是商品类别表的字段 ID,若想能够全部显示相关分类的所有信息,需要重写方法,覆盖对应的外键字段:

    1、goods/serializers.py

    from rest_framework import serializers
    from goods.models import Goods, GoodsCategory
    
    
    class CategorySerializer(serializers.ModelSerializer):
        """
        分类
        """
    
        class Meta:
            model = GoodsCategory
            fields = '__all__'
    
    
    class GoodsSerializer(serializers.ModelSerializer):
        """
        商品
        """
        # 覆盖外键字段 category
        category = CategorySerializer()
        class Meta:
            model = Goods
            fields = '__all__'
    

    2. GenericView 实现商品列表页

    GenericView 继承 APIView,比 APIView 功能更强大, 使用的时候需要指定:queryset、serializer_class

    ListModelMixinlist 方法实现了分页和序列化,视图继承它可以省略自己实现分页和序列化。

    ListModelMixin 源码:

    class ListModelMixin:
        """
        List a queryset.    # 列出查询集
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    

    goods/views.py

    from rest_framework import mixins, viewsets
    from rest_framework import generics
    
    from goods.serializers import GoodsSerializer
    from .models import Goods
    
    class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
        """
        商品列表
        """
        queryset = Goods.objects.all()
        serializer_class = GoodsSerializer
    

    3. 分页

    3.1 全局分页

    配置全局分页只需配置 MxShop/Settings.py 即可:

    REST_FRAMEWORK = {
        #分页
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        #每页显示的个数
        'PAGE_SIZE': 10,
    }
    

    3.2 自定义分页

    自定义分页需要重写分页类,继承 PageNumberPagination,可以自定义:

    • 每页条数
    • 最大页数
    • 获取页码的参数等

    goods/views.py

    from rest_framework.pagination import PageNumberPagination
    from rest_framework import mixins, viewsets
    from rest_framework import generics
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework import filters
    
    from goods.filters import GoodsFilter
    from goods.serializers import GoodsSerializer
    from .models import Goods
    
    class GoodsPagination(PageNumberPagination):
        """
        自定义商品列表分页
        """
        page_size = 10  # 每页显示个数
        page_size_query_param = 'page_size'  # 可以动态改变每页显示的个数
        page_query_param = 'page'  # 页码参数
        max_page_size = 100  # 最多能显示多少页
    
    class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
        """
        商品列表页
        """
        # 分页
        pagination_class = GoodsPagination
        # 这里必须要定义一个默认的排序,否则会报错
        queryset = Goods.objects.all().order_by('id')
        serializer_class = GoodsSerializer
    

    使用:http://127.0.0.1:8000/goods/?page=2&page_size=20

    注意:将全局分页功能注释

    4. viewsets 和 router 配置商品列表路由

    1、MxShop/urls.py

    from django.urls import path, include, re_path
    from django.views.static import serve
    from rest_framework.documentation import include_docs_urls
    from rest_framework.routers import DefaultRouter
    
    import xadmin
    from MxShop.settings import MEDIA_ROOT
    from goods.views import GoodsListViewSet
    
    router = DefaultRouter()
    
    router.register(r'goods', GoodsListViewSet, basename='goods')
    
    urlpatterns = [
        # path('admin/', admin.site.urls),
    
        path('xadmin/', xadmin.site.urls),
        path('ueditor/', include('DjangoUeditor.urls')),
        path('media/<path:path>', serve, {'document_root': MEDIA_ROOT}),
    
        # drf 文档
        path('docs', include_docs_urls(title='hubery')),
        path('api-auth/', include('rest_framework.urls')),
    
        # 商品
        # path('goods/', GoodsListView.as_view(), name='goods-list'),
    
        re_path('^', include(router.urls)),
    ]
    

    2、goods/views.py

    queryset 要定义一个默认的排序,否则会报错:

    from rest_framework.pagination import PageNumberPagination
    from rest_framework import mixins, viewsets
    from rest_framework import generics
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework import filters
    
    from goods.filters import GoodsFilter
    from goods.serializers import GoodsSerializer
    from .models import Goods
    
    class GoodsPagination(PageNumberPagination):
        """
        自定义商品列表分页
        """
        page_size = 10  # 每页显示个数
        page_size_query_param = 'page_size'  # 可以动态改变每页显示的个数
        page_query_param = 'page'  # 页码参数
        max_page_size = 100  # 最多能显示多少页
    
    class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
        """
        商品列表页
        """
        # 分页
        pagination_class = GoodsPagination
        # 这里必须要定义一个默认的排序,否则会报错
        queryset = Goods.objects.all().order_by('id')
        serializer_class = GoodsSerializer
    

    5. 商品过滤和搜索

    5.1 过滤

    drffilter 用法:http://www.django-rest-framework.org/api-guide/filtering/

    1、MxShop/settings.py

    INSTALLED_APPS = [
        'django_filters',
    ]
    

    2、新建 goods/filters.py 用于过滤:

    import django_filters
    
    from .models import Goods
    
    
    class GoodsFilter(django_filters.rest_framework.FilterSet):
        """
        商品过滤
        """
        # field_name 为要过滤的字段,lte 为执行的行为,这里为小于等于本店价格
        price_min = django_filters.NumberFilter(field_name='shop_price', lookup_expr='gte')
        price_max = django_filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
    
        class Meta:
            model = Goods
            fields = ['price_min', 'price_max']
    

    在这里对商品进行过滤,查找 [price_min, price_max] 范围的商品。

    3、goods/views.py

    from django_filters.rest_framework import DjangoFilterBackend
    
    class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
        """
        商品列表页
        """
        # 分页
        pagination_class = GoodsPagination
        # 这里必须要定义一个默认的排序,否则会报错
        queryset = Goods.objects.all().order_by('id')
        serializer_class = GoodsSerializer
    
        # 过滤
        filter_backends = (DjangoFilterBackend, )
    
        # 设置 filter 的类为自定义的类
        filter_class = GoodsFilter
    

    使用:http://127.0.0.1:8000/goods/?price_min=20&price_max=30

    5.2 搜索

    goods/views.py

    from django_filters.rest_framework import DjangoFilterBackend
    
    class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
        """
        商品列表页
        """
        # 分页
        pagination_class = GoodsPagination
        # 这里必须要定义一个默认的排序,否则会报错
        queryset = Goods.objects.all().order_by('id')
        serializer_class = GoodsSerializer
    
        # 过滤
        filter_backends = (DjangoFilterBackend, filters.SearchFilter,)
    
        # 设置 filter 的类为自定义的类
        filter_class = GoodsFilter
    
        # 搜索,=name 为精确搜索,也可以使用正则
        search_fields = ('=name', 'goods_brief')
    

    使用:http://127.0.0.1:8000/goods/?search=水果

    5.3 排序

    goods/views.py

    from django_filters.rest_framework import DjangoFilterBackend
    
    class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
        """
        商品列表页
        """
        # 分页
        pagination_class = GoodsPagination
        # 这里必须要定义一个默认的排序,否则会报错
        queryset = Goods.objects.all().order_by('id')
        serializer_class = GoodsSerializer
    
        # 过滤
        filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    
        # 设置 filter 的类为自定义的类
        filter_class = GoodsFilter
    
        # 搜索,=name 为精确搜索,也可以使用正则
        search_fields = ('=name', 'goods_brief')
    
        # 排序
        ordering_fields = ('sold_num', 'add_time')
    

    使用:http://127.0.0.1:8000/goods/?ordering=sold_num&

  • 相关阅读:
    万亿养老市场如何抢占商机?云巢智慧康养物联网加速器,三招化解ISV痛点!
    13个VSCode使用技巧,开启高效的开发模式
    添零占位 —— 快速生成N个0的六种办法
    使用 dumi 打包 React 组件库并生成文档站点
    Transformer架构记录(四)
    Transformer架构记录(三)
    Transformer架构记录(二)
    Transformer架构记录(一)
    NLP预训练发展小结二(Bert之后)
    p3c 插件,是怎么检查出你那屎山的代码?
  • 原文地址:https://www.cnblogs.com/midworld/p/13629680.html
Copyright © 2020-2023  润新知