码迷,mamicode.com
首页 > 其他好文 > 详细

Django Rest Framework 视图和路由

时间:2018-11-19 23:06:01      阅读:334      评论:0      收藏:0      [点我收藏+]

标签:let   ali   def   pat   实例   pos   get请求   color   方法   

DRF的视图

APIView

#CBV中的View 与rest_framework中APIView

urlpatterns = [
    url(r^book$, BookView.as_view()),
    url(r^book/(?P<id>\d+)$, BookEditView.as_view()),
]

# 在url中都是调用as_view()方法

在看看源码中

技术分享图片

我们能看到,APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。

那我们看看View中的as_view()方法做了什么

技术分享图片

我们看到了在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法但是这里的dispatch方法应该是我们APIView中的

技术分享图片

我们去initialize_request中看下把什么赋值给了request,并且赋值给了self.request, 也就是我们在视图中用的request.xxx到底是什么

技术分享图片

我们看到,这个方法返回的是Request这个类的实例对象我们注意我们看下这个Request类中的第一个参数request,是我们走我们django的时候的原来的request

技术分享图片

我们看到了,这个Request类把原来的request赋值给了self._request, 也就是说以后_request是我们老的request,新的request是我们这个Request类

那我们继承APIView之后请求来的数据都在哪呢

技术分享图片

我们用了rest_framework框架以后,我们的request是重新封装的Request类

request.query_params 存放的是我们get请求的参数

request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求

相比原来的django的request,我们现在的request更加精简,清晰了

第一次封装

技术分享图片
class BookView(APIView):

    def get(self, request):
        query_set = Book.objects.all()
        book_ser = BookSerializer(query_set, many=True)
        return Response(book_ser.data)

    def post(self, request):
        query_set = request.data
        book_ser = BookSerializer(data=query_set)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.validated_data)
        else:
            return Response(book_ser.errors)


class BookEditView(APIView):

    def get(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        book_ser = BookSerializer(query_set)
        return Response(book_ser.data)

    def patch(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        book_ser = BookSerializer(query_set, data=request.data, partial=True)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.validated_data)
        else:
            return Response(book_ser.errors)

    def delete(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        if query_set:
            query_set.delete()
            return Response("")
        else:
            return Response("删除的书籍不存在")
APIView视图
技术分享图片
class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


class ListModelMixin(object):
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class CreateModelMixin(object):
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.validated_data)
        else:
            return Response(serializer.errors)


class RetrieveModelMixin(object):
    def retrieve(self, request, id, *args, **kwargs):
        book_obj = self.get_queryset().filter(pk=id).first()
        book_ser = self.get_serializer(book_obj)
        return Response(book_ser.data)


class UpdateModelMixin(object):
    def update(self, request, id, *args, **kwargs):
        book_obj = self.get_queryset().filter(pk=id).first()
        book_ser = self.get_serializer(book_obj, data=request.data, partial=True)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.validated_data)
        else:
            return Response(book_ser.errors)


class DestroyModelMixin(object):
    def destroy(self, request, id, *args, **kwargs):
        queryset = self.get_queryset()
        try:
            queryset.get(pk=id).delete()
            return Response("")
        except Exception as e:
            return Response("信息有误")
# 我们把公共的部分抽出来 这样不管写多少表的增删改查都变的很简单
# 这样封装后我们的视图会变成这样

class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id, *args, **kwargs):
        return self.retrieve(request, id, *args, **kwargs)

    def patch(self, request, id, *args, **kwargs):
        return self.update(request, id, *args, **kwargs)

    def destroy(self, request, id, *args, **kwargs):
        return self.delete(request, id, *args, **kwargs)
第一次封装

我们封装的GenericAPIView,包括封装每个方法的类,其实框架都帮我们封装好了

我们可以直接继承这些类来实现上面的视图可是还有没有更简单的方法呢我们再次封装一下

第二次封装

技术分享图片
# 上面我们写的继承类太长了~~我们再改改

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


class BookView(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class BookEditView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id, *args, **kwargs):
        return self.retrieve(request, id, *args, **kwargs)

    def patch(self, request, id, *args, **kwargs):
        return self.update(request, id, *args, **kwargs)

    def delete(self, request, id, *args, **kwargs):
        return self.delete(request, id, *args, **kwargs)
第二次封装

这次我们只是让继承变的简单了一点而已,好像并没有什么大的进步

我们可不可以把这两个视图合并成一个视图呢框架给我们提供了一个路由传参的方法

我们看下ViewSetMixin

技术分享图片

actions这个默认参数其实就是我们路由可以进行传参了

下面这个循环可以看出我们要传的参数是一个字段key应该是我们的请求方式,value应该对应我们处理的方法

这样我们每个视图就不用在写函数了因为已经和内部实现的函数相对应了

第三次封装

技术分享图片
urlpatterns = [
    # url(r‘^book$‘, BookView.as_view()),
    # url(r‘^book/(?P<id>\d+)$‘, BookEditView.as_view()),
    url(r^book$, BookView.as_view({"get": "list", "post": "create"})),
    url(r^book/(?P<pk>\d+)$, BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
]

路由urls.py
路由urls.py
技术分享图片
from rest_framework.viewsets import ViewSetMixin


# class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
    
    
# 如果我们再定义一个类
class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    pass


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

第三次封装
第三次封装

 

我们现在的视图就只要写两行就可以了

其实我们写的所有的视图框架都帮我们封装好了

注意一点用框架封装的视图我们url上的那个关键字参数要用pk系统默认的

奉献一张图来看下我们的继承顺序

技术分享图片

DRF的路由

我们上面的路由传参写的特别多框架也帮我们封装好了

技术分享图片
from .views import BookView
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"book", BookView)

urlpatterns = [
    # url(r‘^book$‘, BookView.as_view()),
    # url(r‘^book/(?P<id>\d+)$‘, BookEditView.as_view()),
    # url(r‘^book$‘, BookView.as_view({"get": "list", "post": "create"})),
    # url(r‘^book/(?P<pk>\d+)$‘, BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),

]
urlpatterns += router.urls

路由
路由

 

Django Rest Framework 视图和路由

标签:let   ali   def   pat   实例   pos   get请求   color   方法   

原文地址:https://www.cnblogs.com/beihan/p/9986310.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!