restful(2):视图

 视图部分小结:

 1 # as_view()中的参数:利用参数(一个字典)来指定什么方式用什么方法来执行(哪种请求方式由哪种内部方法来执行)
 2 # 例如 Retrieve时,需要在对应的url中添加有名分组 "pk":?P<pk>  ,这样 retrieve()等方法中的 get_object()方法才能取到相应的记录对象
 3 
 4 # 流程分析:
 5     1. re_path(r"^authors/$",views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
 6     2. re_path(r"^authors/$",ViewSetMixin.as_view({"get":"list","post":"create"}),name="author"),
 7     3. re_path(r"^authors/$",ViewSetMixin.view,name="author"),
 8     
 9     4. 一旦用户访问 /authos/(如 get请求):
10         ViewSetMixin.view():
11             for method, action in actions.items():  # {"get":"list","post":"create"}
12                 handler = getattr(self, action)  # self.list  self.create
13                 setattr(self, method, handler)   # self.get = self.list   # self.post = self.create
14                 
15                 # getattr(self,"get")  # self.list
16                 # getattr(self,"post")  # self.create
17                 
18             return self.dispatch()
19             
20         APIView.dispatch():
21             if request.method.lower() in self.http_method_names:
22                 handler = getattr(self, request.method.lower())
23                 
24                 response = handler(request, *args, **kwargs)  # self.list()
25                 
26                 return response

(1)视图初级版:

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers


class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          #depth=1


class PublshSerializers(serializers.ModelSerializer):

      class Meta:
          model=Publish
          fields="__all__"
          depth=1


class BookViewSet(APIView):

   # 查看所有数据
def get(self,request,*args,**kwargs): book_list=Book.objects.all() bs=BookSerializers(instance=book_list,many=True,context={'request': request}) # 当 BookSerializers 中有 HyperlinkedIdentityField 时,其实例化时需要加上 context={'request':request} return Response(bs.data) # 要返回 bs.data    # 新添加一条记录 def post(self,request,*args,**kwargs): print(request.data)
    

     # 创建记录时的序列化
bs
=BookSerializers(data=request.data,many=False) if bs.is_valid(): print(bs.validated_data) bs.save() # .save() 中有 create() 方法 return Response(bs.data) else: return HttpResponse(bs.errors) class BookDetailViewSet(APIView): def get(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(instance=book_obj,context={'request': request}) return Response(bs.data)
   # 更新数据
def put(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(instance=book_obj,data=request.data,context={'request': request}) # 更新数据时的序列化 if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors) class PublishViewSet(APIView): def get(self,request,*args,**kwargs): publish_list=Publish.objects.all() bs=PublshSerializers(publish_list,many=True,context={'request': request}) return Response(bs.data) def post(self,request,*args,**kwargs): bs=PublshSerializers(data=request.data,many=False) if bs.is_valid(): # print(bs.validated_data) bs.save() return Response(bs.data) else: return HttpResponse(bs.errors) class PublishDetailViewSet(APIView): def get(self,request,pk): publish_obj=Publish.objects.filter(pk=pk).first() bs=PublshSerializers(publish_obj,context={'request': request}) return Response(bs.data) def put(self,request,pk): publish_obj=Publish.objects.filter(pk=pk).first() bs=PublshSerializers(publish_obj,data=request.data,context={'request': request}) if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors)

(2)mixin类编写视图

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):

    queryset = Book.objects.all()  # queryset 变量表示要接收的 queryset;queryset这个名字是固定的
    serializer_class = BookSerializers  # serializer_class 变量表示要用到的序列化的类;serializer_class 这个名字是固定的

    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 BookDetailViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

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

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

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

(3)使用通用的基于类的视图

上面通过使用mixin类,可以使用更少的代码重写这些视图,但还是可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,可以通过使用它来简化我们的views.py模块

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(generics.ListCreateAPIView):

    queryset = Book.objects.all()
    serializer_class = BookSerializers

class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

class PublishViewSet(generics.ListCreateAPIView):

    queryset = Publish.objects.all()
    serializer_class = PublshSerializers

class PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublshSerializers

(4)viewsets.ModelViewSet

urls.py部分:

from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r"^books/$",views.BookModelView.as_view({"get":"list","post":"create"})),
    re_path(r"^books/(?P<pk>d+)/$",views.BookModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"})),
    # 需要在对应的url中添加有名分组 "pk":?P<pk>  ,这样 retrieve()等方法中的 get_object()方法才能取到相应的记录对象
    re_path(r"^publish/$",views.PublishModelView.as_view({"get":"list","post":"create"}),name="publish"),
    re_path(r"^publish/(?P<pk>d+)/$",views.PublishModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="publish_detail"),
    re_path(r"^login/$",views.LoginView.as_view(),name="login"),
]


# as_view() 是否可以加参数,取决于视图的类是否继承 ViewSetMixin

views.py部分:

from app01 import models
from app01 import serializer

from rest_framework.views import APIView
from rest_framework.response import Response
# Create your views here.

from rest_framework import viewsets


class BookModelView(viewsets.ModelViewSet):
    queryset = models.Book.objects.all()  # queryset 表示要处理的数据;queryset这个变量名是固定的
    serializer_class = serializer.BookSerializers  # serializer_class 表示 所要用到的 序列化的类;serializer_class 是固定写法


class PublishModelView(viewsets.ModelViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = serializer.PublishSerializers

 

继承的类:

class View(object):
class APIView(View)
class GenericAPIView(views.APIView)
class GenericViewSet(ViewSetMixin,generics.GenericAPIView)
class ModelViewSet(
    mixins.CreateModelMixin,
    mixins.RetriveModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    mixins.ListModelMixin,
    GenericViewSet
)

from rest_framework.views import APIView # ** 继承 APIView 就是要写原生的 接口(API)
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import GenericViewSet  # GenericViewSet继承的ViewSetMixin,决定了 as_view() 中能加参数
from rest_framework.viewsets import ModelViewSet  # ** ModelViewSet 继承了增删改查

补充: model类.objects.update_or_create(user=user_obj,default=...)  # 表中没有就创建,有就更新;# 返回一个元组:第一个是对象,第二个是布尔值

原文地址:https://www.cnblogs.com/neozheng/p/9577544.html