Django rest framework(8)---- 視圖和渲染器

django rest framework 之視圖

序列化器    PagerSerialiserpython

from rest_framework import serializers
from api import models


class PagerSerialiser(serializers.ModelSerializer):
    class Meta:
        model = models.Role
        fields = "__all__"

APIview

ApiAPIView 實現分頁的寫法以下數據庫

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
from api import models

class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 2
    ordering = 'id'
    page_size_query_param = None
    max_page_size = None

class Pager1View(APIView):

    def get(self,request,*args,**kwargs):

        # 獲取全部數據
        roles = models.Role.objects.all()

        # 建立分頁對象
        # pg = CursorPagination()
        pg = MyCursorPagination()

        # 在數據庫中獲取分頁的數據
        pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

        # 對數據進行序列化
        ser = PagerSerialiser(instance=pager_roles, many=True)

        # return Response(ser.data)
        return pg.get_paginated_response(ser.data)

添加路由django

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/pager1/$', views.Pager1View.as_view()),
]

 測試結果api

http://127.0.0.1:8000/api/v1/pager1/

 

 

GenericAPIView 咱們通常不用,沒有比APIView 簡單多少

GenericAPIView 是繼承APIView的,因此對APIView 進行了一些功能的封裝,一樣實現上述功能,代碼以下app

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.generics import GenericAPIView

class View1View(GenericAPIView):
    queryset = models.Role.objects.all() # 指定查詢的數據
    serializer_class = PagerSerialiser    # 序列化
    pagination_class = PageNumberPagination  # 分頁
    def get(self,request,*args,**kwargs):
        # 獲取數據
        roles = self.get_queryset() # models.Role.objects.all()

        # [1, 1000,]     [1,10]
        pager_roles = self.paginate_queryset(roles) # 獲取分頁後的結果

        # 序列化
        ser = self.get_serializer(instance=pager_roles,many=True)

        return Response(ser.data)

 

源碼以下所示ide

class GenericAPIView(views.APIView):
    """
    Base class for all other generic views.
    """
    # You'll need to either set these attributes,
    # or override `get_queryset()`/`get_serializer_class()`.
    # If you are overriding a view method, it is important that you call
    # `get_queryset()` instead of accessing the `queryset` property directly,
    # as `queryset` will get evaluated only once, and those results are cached
    # for all subsequent requests.
    queryset = None
    serializer_class = None

    # If you want to use object lookups other than pk, set 'lookup_field'.
    # For more complex lookup requirements override `get_object()`.
    lookup_field = 'pk'
    lookup_url_kwarg = None

    # The filter backend classes to use for queryset filtering
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

    # The style to use for queryset pagination.
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get_queryset(self):
        """
        Get the list of items for this view.
        This must be an iterable, and may be a queryset.
        Defaults to using `self.queryset`.

        This method should always be used rather than accessing `self.queryset`
        directly, as `self.queryset` gets evaluated only once, and those results
        are cached for all subsequent requests.

        You may want to override this if you need to provide different
        querysets depending on the incoming request.

        (Eg. return a list of items that is specific to the user)
        """
        assert self.queryset is not None, (
            "'%s' should either include a `queryset` attribute, "
            "or override the `get_queryset()` method."
            % self.__class__.__name__
        )

        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            # Ensure queryset is re-evaluated on each request.
            queryset = queryset.all()
        return queryset

    def get_object(self):
        """
        Returns the object the view is displaying.

        You may want to override this if you need to provide non-standard
        queryset lookups.  Eg if objects are referenced using multiple
        keyword arguments in the url conf.
        """
        queryset = self.filter_queryset(self.get_queryset())

        # Perform the lookup filtering.
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        assert lookup_url_kwarg in self.kwargs, (
            'Expected view %s to be called with a URL keyword argument '
            'named "%s". Fix your URL conf, or set the `.lookup_field` '
            'attribute on the view correctly.' %
            (self.__class__.__name__, lookup_url_kwarg)
        )

        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)

        # May raise a permission denied
        self.check_object_permissions(self.request, obj)

        return obj

    def get_serializer(self, *args, **kwargs):
        """
        Return the serializer instance that should be used for validating and
        deserializing input, and for serializing output.
        """
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)

    def get_serializer_class(self):
        """
        Return the class to use for the serializer.
        Defaults to using `self.serializer_class`.

        You may want to override this if you need to provide different
        serializations depending on the incoming request.

        (Eg. admins get full serialization, others get basic serialization)
        """
        assert self.serializer_class is not None, (
            "'%s' should either include a `serializer_class` attribute, "
            "or override the `get_serializer_class()` method."
            % self.__class__.__name__
        )

        return self.serializer_class

    def get_serializer_context(self):
        """
        Extra context provided to the serializer class.
        """
        return {
            'request': self.request,
            'format': self.format_kwarg,
            'view': self
        }

    def filter_queryset(self, queryset):
        """
        Given a queryset, filter it with whichever filter backend is in use.

        You are unlikely to want to override this method, although you may need
        to call it either from a list view, or from a custom `get_object`
        method if you want to apply the configured filtering backend to the
        default queryset.
        """
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset

    @property
    def paginator(self):
        """
        The paginator instance associated with the view, or `None`.
        """
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        """
        Return a single page of results, or `None` if pagination is disabled.
        """
        if self.paginator is None:
            return None
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

    def get_paginated_response(self, data):
        """
        Return a paginated style `Response` object for the given output data.
        """
        assert self.paginator is not None
        return self.paginator.get_paginated_response(data)
View Code

 

 添加路由函數

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/pager1/$', views.Pager1View.as_view()),
    # url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view()),

]

  

測試結果以下測試

http://127.0.0.1:8000/api/v1/v1/

 

 

GenericViewSet

 它繼承的是ui

 

它在 GenericAPIView 的基礎上增長了路由和視圖函數的限制關係,在url中指定的方法類視圖中必須對應this

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.viewsets import GenericViewSet

class View1View(GenericViewSet):
    queryset = models.Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination

    def list(self, request, *args, **kwargs):
        # 獲取數據
        roles = self.get_queryset()  # models.Role.objects.all()

        # [1, 1000,]     [1,10]
        pager_roles = self.paginate_queryset(roles)

        # 序列化
        ser = self.get_serializer(instance=pager_roles, many=True)

        return Response(ser.data)

 添加路由

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/pager1/$', views.Pager1View.as_view()),
    # url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view()),
    url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list'})),

]

測試結果以下

 

 

ModelViewSet

它繼承的類以下,它實現的功能比較強大,只需簡單的配置,就不須要咱們去寫增刪改查和局部更新,在這裏能夠解決咱們這樣的一個問題,當咱們查詢全部數據的時候直接會去用list方法,查詢一個經過url/1 會執行 retrieve 方法 ,省去咱們的判斷

 

繼承的其中一個類的源代碼以下,咱們能夠看到只要繼承了這個方法,咱們就不須要寫list 查詢所有數據的方法  

class ListModelMixin(object):
    """
    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)

 

 經過繼承modelViewSet實現分頁的功能以下

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.viewsets import GenericViewSet,ModelViewSet

class View1View(ModelViewSet):
    queryset = models.Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination

 

 配置路由

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/pager1/$', views.Pager1View.as_view()),
    # url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view()),
    # url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list'})),
    url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$', views.View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),

]

 

 

 測試結果以下

http://127.0.0.1:8000/api/v1/v1/1/

  

 

 

 在上面咱們能夠看到,咱們能夠對這一條數據,進行增刪改查的操做

 

django rest framework 之渲染器

經過渲染器能夠指定數據返回的格式

註冊 rest_framework

 

全局配置

REST_FRAMEWORK = {
    
    "DEFAULT_RENDERER_CLASSES":[
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}

 

局部配置

class TestView(APIView):
    # renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
    def get(self, request, *args, **kwargs):
        # 獲取全部數據
        roles = models.Role.objects.all()

        # 建立分頁對象
        # pg = CursorPagination()
        pg = MyCursorPagination()

        # 在數據庫中獲取分頁的數據
        pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)

        # 對數據進行序列化
        ser = PagerSerialiser(instance=pager_roles, many=True)

        return Response(ser.data)
相關文章
相關標籤/搜索