ModelModelSerializer和視圖
阿新 • • 發佈:2018-06-21
hasattr IE names resp generic fields 接受 set方法 troy
ModelModelSerializer
ModelModelSerializer和ModelForm組件很相似
1.自當義類繼承ModelSerializer
from rest_framework.serializers import ModelSerializer class BookModelSerializers(ModelSerializer): class Meta: model=models.Book fields="__all__"
2.處理get請求:
url(r‘^book/$‘, views.BookView.as_view())
fromrest_framework.views import APIView from rest_framework.response import Response class BookView(APIView): def get(self, request): book_list = models.Book.objects.all() bs = BookModelSerializers(book_list, many=True) return Response(bs.data) # 序列化接口,將bs的所有內容都返回 #在處理get請求時只是將BookSerializers換為BookModelSerializers
3.處理post請求:
def post(self,request): bs=BookModelSerializers(data=request.data,) if bs.is_valid():# 校驗字段接口 bs.save() #創建記錄接口create return Response(bs.data) # 序列化接口 return Response(bs.errors) # 序列化接口
接受到數據就,進行校驗,如果合格,就存起來(save),否則就將錯誤顯示出來
4.處理查看指定個數據,編輯和刪除請求:
url(r‘^book/(\d+)/$‘, views.BookDetailView.as_view())
class BookDetailView(APIView): def get(self,request,pk): #對單個對象進行序列化 book=models.Book.objects.filter(pk=pk).first() bs=BookModelSerializers(book) #序列化具體的對象 return Response(bs.data) def put(self,request,pk): book = models.Book.objects.filter(pk=pk).first() bs=BookModelSerializers(data=request.data,instance=book) if bs.is_valid(): bs.save() return Response(bs.data) else:return Response(bs.errors) def delete(self, request,pk): models.Book.objects.filter(pk=pk).first().delete() #如果刪除就返回空 return Response()
編寫視圖
使用ModelModelSerializer自定義編寫視圖
url
url(r‘^book/$‘, views.BookView.as_view()), url(r‘^book/(\d+)/$‘, views.BookDetailView.as_view()),
views.py
from rest_framework.serializers import ModelSerializer class BookModelSerializers(ModelSerializer): class Meta: model=models.Book fields="__all__"
from rest_framework.views import APIView from rest_framework.response import Response class BookView(APIView): def get(self,request): book_list=models.Book.objects.all() bs=BookModelSerializers(book_list,many=True) return Response(bs.data) # 序列化接口,將bs的所有內容都返回 def post(self,request): print("request.data", request.data) bs=BookModelSerializers(data=request.data,) if bs.is_valid():# 校驗字段接口 bs.save() #創建記錄接口create return Response(bs.data) # 序列化接口 return Response(bs.errors) # 序列化接口BookView
class BookDetailView(APIView): def get(self,request,pk): #對單個對象進行序列化 book=models.Book.objects.filter(pk=pk).first() bs=BookModelSerializers(book) return Response(bs.data) def put(self,request,pk): book = models.Book.objects.filter(pk=pk).first() ###bs為序列化對象 bs=BookModelSerializers(data=request.data,instance=book) if bs.is_valid(): bs.save() return Response(bs.data) else:return Response(bs.errors) def delete(self, request,pk): models.Book.objects.filter(pk=pk).first().delete() #如果刪除就返回空 return Response()BookDetailView
使用混合(mixins)
url(r‘^publish/$‘, views.PublishView.as_view()), url(r‘^publish/(?P<pk>\d+)/$‘, views.PublishDetailView.as_view()),
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework import mixins
from rest_framework import generics
class PublishModelSerializer(ModelSerializer): class Meta: model=models.Publish fields="__all__"
class PublishView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishModelSerializer def get(self,request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self,request, *args, **kwargs): return self.create(request, *args, **kwargs)PublishView
class PublishDetailView(mixins.DestroyModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishModelSerializer 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)PublishDetailView
使用通用的基於類的視圖
url(r‘^authors/$‘, views.AuthorsView.as_view()), url(r‘^authors/(?P<pk>\d+)/$‘, views.AuthorsDetailView.as_view()),
class AuthorModelSerializers(ModelSerializer): class Meta: model=models.Author fields="__all__"
class AuthorsView(generics.ListCreateAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers class AuthorsDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers
viewsets.ModelViewSet
url
url(r‘^authors/$‘, views.AuthorsModelView.as_view({"get": "list", "post": "create"}),), url(r‘^authors/(?P<pk>\d+)/$‘, views.AuthorsModelView.as_view({ ‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘ }),
views
from rest_framework.viewsets import ModelViewSet from app01 import models class AuthorsModelView(ModelViewSet): queryset = models.Author.objects.all() serializer_class = AuthorModelSerializers
使用viewsets.ModelViewSet方法便捷高效,具體流程:
1.django啟動
Djago啟動過後 views.AuthorsModelView.as_view({"get": "list", "post": "create"})
和views.AuthorsModelView.as_view({
‘get‘: ‘retrieve‘,
‘put‘: ‘update‘,
‘delete‘: ‘destroy‘
})都會被執行,找AuthorsModelView中的as_view方法,無此方法,去父類ModelViewSet查找
2.ModelViewSet源碼:
class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): pass
ModelViewSet中無s_view方法,去父類中查找
CreateModelMixin中放著新建數據的函數
RetrieveModelMixin中放著查看某條數據的函數
UpdateModelMixin中放著更新數據的函數
DestroyModelMixin中放著刪除數據的函數
ListModelMixin中放著展示全部數據的函數
去GenericViewSet中查找as_view方法
3.執行ViewSetMixin中的as_view
GenericViewSet源碼:
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):pass
GenericViewSet中無as_view方法,向其父類中查找
執行ViewSetMixin中的as_view。ViewSetMixin源碼:
class ViewSetMixin(object): def as_view(cls, actions=None, **initkwargs): def view(request, *args, **kwargs): self = cls(**initkwargs) self.action_map = actions for method, action in actions.items(): handler = getattr(self, action) setattr(self, method, handler) if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) return csrf_exempt(view)
找到as_view方法後,執行此方法返回view
url(r‘^authors/$‘, views.AuthorsModelView.as_view({"get": "list", "post": "create"}), ), url(r‘^authors/(?P<pk>\d+)/$‘, views.AuthorsModelView.as_view({ ‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘ }), 相當於: url(r‘^authors/$‘, view), url(r‘^authors/(?P<pk>\d+)/$‘, view)
這是啟動django後就完成的工作,當用戶發送請求時,view執行
4.發送請求,執行ViewSetMixin中的view方法
def view(request, *args, **kwargs): self = cls(**initkwargs) for method, action in actions.items(): handler = getattr(self, action) setattr(self, method, handler) return self.dispatch(request, *args, **kwargs)
最終的返回值時執行dispatch函數,在著之前的for循環的作用?
需要知道actions是什麽,但是函數中並沒有actions這個值,在這裏使用了閉包
class ViewSetMixin(object): def as_view(cls, actions=None, **initkwargs): def view(request, *args, **kwargs): for method, action in actions.items():pass
在django啟動時,執行as_view時傳的有參數,
views.AuthorsModelView.as_view({"get": "list", "post": "create"})
在執行as_view時,默認參數actions接收到了{"get": "list", "post": "create"},在執行view時,使用這些值,不同的url執行actions接收值不同,
在執行view時也不同
for method, action in actions.items(): handler = getattr(self, action) setattr(self, method, handler)
method的值就是"get","post",action為"list","create"
handeler的值為self.list/self.create
setattr重新賦值,如setattr(self, "get",self.list)等同於再進行getattr(self,"get")
5.執行self.dispatch,執行APIView中的dispatch
AuthorsModelView,ModelViewSet,GenericViewSet,GenericAPIView
均無dispatch方法,在APIView中有dispatch方法
class APIView(View): def dispatch(self, request, *args, **kwargs): request = self.initialize_request(request, *args, **kwargs) self.request = request if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) return self.response
執行APIView中的dispatch方法:
handler = getattr(self, request.method.lower(),self.http_method_not_allowed)
執行反射時,如果發來的請求get,此時handler不再是self.get,而是self.list.是因為在執行ViewSetMixin中的view方法時
setattr(self, method, handler)重新賦值了
執行handler函數,response=self.list(request, *args, **kwargs),去AuthorsModelView中list方法
class ListModelMixin(object): 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)
handler執行後的結果返回給response,dispatch函數將response返回給view,view在頁面上顯示出來
ModelModelSerializer和視圖