Django框架的學習筆記

基於Django的REST framework 框架的視圖說明(二)

開發環境:Ubuntu16.04+Python3.5x+Pycharm2018.2python

包含方法和屬性的通用視圖基類及擴展類的繼承關係數據庫

clipboard.png

兩個基類

APIView類

GenericAPIView類

本篇主要說明GenericAPIView類
rest_framework.generics.GenericAPIView後端

繼承自APIView,增長了對於列表視圖和詳情視圖可能用到的通用支持方法。一般使用時,可搭配一個或多個Mixin擴展類.api

支持定義的屬性:框架

列表視圖與詳情視圖通用:
queryset 列表視圖的查詢集
serializer_class 視圖使用的序列化器ide

列表視圖使用:
pagination_class 分頁控制類
filter_backends 過濾控制後端ui

詳情頁視圖使用:
lookup_field 查詢單一數據庫對象時使用的條件字段,默認爲'pk'
lookup_url_kwarg 查詢單一數據時URL中的參數關鍵字名稱,默認與look_field相同this

源代碼以下:lua

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

支持定義的方法:url

列表視圖與詳情視圖通用:

get_queryset(self)
源碼以下:

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

返回視圖使用的查詢集,是列表視圖與詳情視圖獲取數據的基礎,默認返回queryset屬性,能夠重寫,例如:

def get_queryset(self):
    user = self.request.user
    return user.accounts.all()

get_serializer_class(self)

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

返回序列化器類,默認返回serializer_class,能夠重寫,例如:

def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer

get_serializer(self, args, **kwargs)
返回序列化器對象,被其餘視圖或擴展類使用,若是咱們在視圖中想要獲取序列化器對象,能夠直接調用此方法。

注意,在提供序列化器對象的時候,REST framework會向對象的context屬性補充三個數據:request、format、view,這三個數據對象能夠在定義序列化器時使用。

詳情視圖使用:

get_object(self)

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

返回詳情視圖所需的模型類數據對象,默認使用lookup_field參數來過濾queryset。 在試圖中能夠調用該方法獲取詳情信息的模型類對象。

若詳情訪問的模型類對象不存在,會返回404。

def get_object_or_404(queryset, *filter_args, **filter_kwargs):
    """
    Same as Django's standard shortcut, but make sure to also raise 404
    if the filter_kwargs don't match the required types.
    """
    try:
        return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
    except (TypeError, ValueError, ValidationError):
        raise Http404

該方法會默認使用APIView提供的check_object_permissions方法檢查當前對象是否有權限被訪問。

舉例:以圖書與英雄案例(如水滸傳與英雄)

# GET /books/
# url(r'^books/$', views.BookListAPIView.as_view()) 對應的路由
class BookListAPIView(GenericAPIView):
    """
    數據查詢集
    """
    queryset = BookInfo.objects.all()  # 數據庫查詢集
    serializer_class = BookInfoSerializer

    def get(self,request):
        # 數據庫查詢
        qs = self.get_queryset()
        # 構建序列化器對象,進行序列化操做
        serializer = self.get_serializer(qs,many = True)

        return  Response(serializer.data)

# GET /books/<pk>/
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()) 對應的路由
class BookDetailAPIView(GenericAPIView):
    queryset = BookInfo.objects.all()

    serializer_class = BookInfoSerializer


    def get(self,request,pk):
        """
        查詢單個
        :param query:
        :return:
        """
        book = self.get_object()
        serializer = self.get_serializer(book)

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