3.商品列表页

1. django的view实现商品列表页

  urls.py

1 from django.conf.urls import url, include
2 from django.contrib import admin
3 
4 urlpatterns = [
5     url(r'^goods/', include('goods.urls'), name='goods'),
6     url(r'^admin/', admin.site.urls),
7 ]

    goods/urls.py

1 from django.conf.urls import url
2 from goods.views_base import GoodListView
3 
4 urlpatterns = [
5     url(r'^list/$', GoodListView.as_view(), name='goods_list')
6 ]

    goods/views.py

 1 import json
 2 from django.views.generic.base import View
 3 from django.http import HttpResponse
 4 from goods.models import Goods
 5 
 6 class GoodListView(View):
 7     def get(self, request):
 8         goods = Goods.objects.all()[:10]
 9         json_list = []
10         for good in goods:
11             json_dic = {}
12             json_dic['name'] = good.name
13             json_dic['market_price'] = good.market_price
14             json_list.append(json_dic)
15         return HttpResponse(json.dumps(json_list), content_type='application/json')

    chome jsonview安装 浏览器结构化显示json格式数据

    https://www.cnblogs.com/whycxb/p/7126116.html

 2.django的serializer序列化model

    之前没发现这个用法,以前都是直接遍历,重新赋值,做了一堆无用功。

 1 import json
 2 from django.views.generic.base import View
 3 from django.http import JsonResponse
 4 from django.core import serializers
 5 from goods.models import Goods
 6 
 7 class GoodListView(View):
 8     def get(self, request):
 9         goods = Goods.objects.all()[:10]
10 
11         # json.dumps: dict转成str
12         # json.loads: str转成dict
13         json_list = json.loads(serializers.serialize('json', goods))
14         return JsonResponse(json_list, safe=False)

3.apiview方式实现商品列表页

  安装DRF(参考:http://www.django-rest-framework.org/)

1 pip install djangorestframework
2 pip install markdown       # Markdown support for the browsable API.
3 pip install django-filter  # Filtering support
4 pip install django-guardian
5 pip install coreapi

    配置urls.py与goods/urls.py

1 from django.conf.urls import url, include
2 from django.contrib import admin
3 from rest_framework.documentation import include_docs_urls
4 
5 urlpatterns = [
6     url(r'^goods/', include('goods.urls'), name='goods'),
7     url(r'^admin/', admin.site.urls),
8     url(r'docs/', include_docs_urls(title='接口说明'))
9 ]
1 from django.conf.urls import url
2 from goods.views_base import GoodListView
3 from goods.views import GoodsList as GoodsListDRF
4 
5 urlpatterns = [
6     url(r'^list/$', GoodListView.as_view(), name='goods_list'),
7     url(r'^list_drf/$', GoodsListDRF.as_view(), name='goods_list_drf'),
8 ]

    编写:views.py 和 goods/serializers.py

 1 from rest_framework.views import APIView
 2 from rest_framework.response import Response
 3 
 4 from .models import Goods
 5 from .serializers import GoodsSerializer
 6 
 7 class GoodsList(APIView):
 8     """
 9     接口描述
10     List all goods.
11     """
12     def get(self, request, format=None):
13         goods = Goods.objects.all()
14         serializer = GoodsSerializer(goods, many=True)
15         return Response(serializer.data)
1 from rest_framework import serializers
2 from .models import Goods
3 
4 class GoodsSerializer(serializers.Serializer):
5     id = serializers.IntegerField()
6     name = serializers.CharField(max_length=100, required=True)
7     goods_front_image = serializers.ImageField()

    创建数据接口(直接参考官方文档,这里并没有测试它,所以就不列出例子了)、ModelSerializers使用

 1 from rest_framework import serializers
 2 from .models import Goods, GoodsCategory
 3 
 4 class GoodsCategorySerializer(serializers.ModelSerializer):
 5     class Meta:
 6         model = GoodsCategory
 7         fields = "__all__"
 8 
 9 class GoodsSerializer(serializers.ModelSerializer):
10     # 覆盖原有字段内容
11     category = GoodsCategorySerializer()
12     class Meta:
13         model = Goods
14         # 定义显示那些字段
15         # fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
16         # 显示所有字段
17         fields = "__all__"

    GenericAPIView 的使用(views.py)

 1 from rest_framework import mixins
 2 from rest_framework import generics
 3 
 4 from .models import Goods
 5 from .serializers import GoodsSerializer
 6 
 7 class GoodsList(mixins.ListModelMixin, generics.GenericAPIView):
 8     """
 9     商品列表页
10     """
11     queryset = Goods.objects.all()
12     serializer_class = GoodsSerializer
13 
14     def get(self, request, *args, **kwargs):
15         return self.list(request, *args, **kwargs)

    ListAPIView的使用(views.py):

 1 from rest_framework.generics import ListAPIView
 2 
 3 from .models import Goods
 4 from .serializers import GoodsSerializer
 5 
 6 class GoodsList(ListAPIView):
 7     """
 8     商品列表页(ListAPIView)
 9     """
10     queryset = Goods.objects.all()
11     serializer_class = GoodsSerializer

    添加分页功能(settings.py)设置:

1 REST_FRAMEWORK = {
2     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
3     'PAGE_SIZE': 2
4 }

    深度分页功能:

 1 from rest_framework.generics import ListAPIView
 2 from rest_framework.pagination import PageNumberPagination
 3 
 4 from .models import Goods
 5 from .serializers import GoodsSerializer
 6 
 7 class GoodsPagination(PageNumberPagination):
 8     page_size = 10
 9     page_size_query_param = 'page_size'
10     max_page_size = 10000
11 
12 class GoodsList(ListAPIView):
13     """
14     商品列表页(ListAPIView)
15     """
16     queryset = Goods.objects.all()
17     serializer_class = GoodsSerializer
18     pagination_class = GoodsPagination

     使用viewsets重构代码:

 1 from rest_framework.pagination import PageNumberPagination
 2 from rest_framework import viewsets, mixins
 3 
 4 from .models import Goods
 5 from .serializers import GoodsSerializer
 6 
 7 class GoodsPagination(PageNumberPagination):
 8     page_size = 10
 9     page_size_query_param = 'page_size'
10     page_query_param = "p"
11     max_page_size = 10000
12 
13 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
14     """
15     商品列表页(ListAPIView)
16     """
17     queryset = Goods.objects.all()
18     serializer_class = GoodsSerializer
19     pagination_class = GoodsPagination

    显示绑定URL和viewsets:

 1 from django.conf.urls import url
 2 from goods.views_base import GoodListView
 3 from goods.views import GoodsListViewSet
 4 
 5 goods_list = GoodsListViewSet.as_view({
 6     'get': 'list',
 7 })
 8 
 9 urlpatterns = [
10     url(r'^list/$', GoodListView.as_view(), name='goods_list'),
11     url(r'^list_drf/$', goods_list, name='goods_list_drf'),
12 ]

    使用routers:

 1 from django.conf.urls import url, include
 2 from django.contrib import admin
 3 from rest_framework.documentation import include_docs_urls
 4 from rest_framework.routers import DefaultRouter
 5 
 6 from goods.views import GoodsListViewSet
 7 
 8 router = DefaultRouter()
 9 router.register(r"goods", GoodsListViewSet)
10 
11 urlpatterns = [
12     # url(r'^goods/', include('goods.urls'), name='goods'),
13     url('^', include(router.urls)),
14     url(r'^admin/', admin.site.urls),
15     url(r'^api-auth/', include('rest_framework.urls')),
16     url(r'docs/', include_docs_urls(title='接口说明'))
17 ]

 4.drf的Apiview、GenericView、Viewset和router的原理分析

    结构:

 1 GenericViewSet()  --drf
 2   GenericAPIView    --drf
 3     APIView      --drf
 4       View        --django
 5     
 6 mixins
 7   CreateModelMixin
 8   ListModelMixin
 9   RetrieveModelMixin
10   UpdateModelMixin
11   DestroyModelMixin

    为什么router直接能映射到相应的view中并返回数据?

    routers/SimpleRouter

 1 class SimpleRouter(BaseRouter):
 2 
 3     routes = [
 4         # List route.
 5         Route(
 6             url=r'^{prefix}{trailing_slash}$',
 7             mapping={
 8                 'get': 'list',
 9                 'post': 'create'
10             },
11 ......

    minixs/ListModelMixin:

 1 class ListModelMixin(object):
 2     """
 3     List a queryset.
 4     """
 5     def list(self, request, *args, **kwargs):
 6         queryset = self.filter_queryset(self.get_queryset())
 7 
 8         page = self.paginate_queryset(queryset)
 9         if page is not None:
10             serializer = self.get_serializer(page, many=True)
11             return self.get_paginated_response(serializer.data)
12 
13         serializer = self.get_serializer(queryset, many=True)
14         return Response(serializer.data)

    viewset/ViewsetMixin:

class ViewSetMixin(object):
    """
    This is the magic.

    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.

    For example, to create a concrete view binding the 'GET' and 'POST' methods
    to the 'list' and 'create' actions...

    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    """

    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
......

 5.drf的request和response

    可参考官方文档:

        http://www.django-rest-framework.org/api-guide/requests/

        http://www.django-rest-framework.org/api-guide/responses/

    中文版:

        https://darkcooking.gitbooks.io/django-rest-framework-cn/content/chapter2.html

        http://www.chenxm.cc/post/290.html

6.drf的过滤功能

  (1)自己写的过滤器

 1 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
 2     """
 3     商品列表页(ListAPIView)
 4     """
 5     queryset = Goods.objects.all()
 6     serializer_class = GoodsSerializer
 7     pagination_class = GoodsPagination
 8 
 9     def get_queryset(self):
10         queryset = Goods.objects.all()
11         price_min = self.request.query_params.get('price_min', 0)
12         if price_min:
13             queryset = queryset.filter(shop_price__gt = int(price_min))
14 
15         return queryset

   (2)django-filter普通应用

 1 # 安装django-filter
 2 pip install django-filter
 3 # 添加进INSTALLED_APPS
 4 INSTALLED_APPS = [
 5    ...
 6     'django_filters',
 7 ]
 8 # views.py中应用
 9 ...
10 from django_filters.rest_framework import DjangoFilterBackend
11 ...
12 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
13    ...
14     filter_backends = (DjangoFilterBackend,)
15     filter_fields = ('name', 'shop_price')

    (3)django-filter区间搜索

    filters.py

 1 import django_filters
 2 from .models import Goods
 3 
 4 class GoodsFilter(django_filters.FilterSet):
 5     '''
 6     商品过滤类
 7     '''
 8     price_min = django_filters.NumberFilter(name='shop_price', lookup_expr='gte')
 9     price_max = django_filters.NumberFilter(name='shop_price', lookup_expr='lte')
10     # 模糊查询
11     name = django_filters.CharFilter(name='name', lookup_expr="icontains")
12 
13     class Meta:
14         model = Goods
15         fields = ['price_min', 'price_max', 'name']

    views.py

 1 from rest_framework.pagination import PageNumberPagination
 2 from rest_framework import viewsets, mixins
 3 from django_filters.rest_framework import DjangoFilterBackend
 4 
 5 from .models import Goods
 6 from .serializers import GoodsSerializer
 7 from .filters import GoodsFilter
 8 
 9 class GoodsPagination(PageNumberPagination):
10     page_size = 10
11     page_size_query_param = 'page_size'
12     page_query_param = "p"
13     max_page_size = 10000
14 
15 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
16     """
17     商品列表页(ListAPIView)
18     """
19     queryset = Goods.objects.all()
20     serializer_class = GoodsSerializer
21     pagination_class = GoodsPagination
22     filter_backends = (DjangoFilterBackend,)
23     filter_class = GoodsFilter

     对应的官方文档:https://django-filter.readthedocs.io/en/master/guide/rest_framework.html

 7.drf的搜索和排序

 1 from rest_framework.pagination import PageNumberPagination
 2 from rest_framework import viewsets, mixins, filters
 3 from django_filters.rest_framework import DjangoFilterBackend
 4 
 5 from .models import Goods
 6 from .serializers import GoodsSerializer
 7 from .filters import GoodsFilter
 8 
 9 class GoodsPagination(PageNumberPagination):
10     page_size = 10
11     page_size_query_param = 'page_size'
12     page_query_param = "p"
13     max_page_size = 10000
14 
15 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
16     """
17     商品列表页(ListAPIView)
18     """
19     queryset = Goods.objects.all()
20     serializer_class = GoodsSerializer
21     pagination_class = GoodsPagination
22     filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
23     filter_class = GoodsFilter
24 
25     search_fields = ('name', '^goods_desc')
26     ordering_fields = ('sold_num', 'add_time')

 

posted @ 2018-01-22 09:29  KD-VS-WB  阅读(142)  评论(0)    收藏  举报