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=...) # 表中没有就创建,有就更新;# 返回一个元组:第一个是对象,第二个是布尔值
Code your future.