rest-framework之APIView 序列化組件

rest-framework之APIView

一 安裝djangorestframework

方式一:pip3 install djangorestframeworkpython

方式二:pycharm圖形化界面安裝linux

方式三:pycharm命令行下安裝(裝在當前工程所用的解釋器下)git

二 djangorestframework的APIView分析

  • as_view 方法數據庫

    @classmethod
      def as_view(cls, **initkwargs):
          """
          Store the original class on the view function.
    
          This allows us to discover information about the view when we do URL
          reverse lookups.  Used for breadcrumb generation.
          """
          if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
              def force_evaluation():
                  raise RuntimeError(
                      'Do not evaluate the `.queryset` attribute directly, '
                      'as the result will be cached and reused between requests. '
                      'Use `.all()` or call `.get_queryset()` instead.'
                  )
              cls.queryset._fetch_all = force_evaluation
    
          view = super(APIView, cls).as_view(**initkwargs)
          view.cls = cls
          view.initkwargs = initkwargs
    
          # Note: session based authentication is explicitly CSRF validated,
          # all other authentication is CSRF exempt.
          return csrf_exempt(view)
  • dispatch 方法django

    def dispatch(self, request, *args, **kwargs):
          """
          `.dispatch()` is pretty much the same as Django's regular dispatch,
          but with extra hooks for startup, finalize, and exception handling.
          """
          self.args = args
          self.kwargs = kwargs
          request = self.initialize_request(request, *args, **kwargs)
          self.request = request
          self.headers = self.default_response_headers  # deprecate?
    
          try:
              self.initial(request, *args, **kwargs)
    
              # Get the appropriate handler method
              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)
    
          except Exception as exc:
              response = self.handle_exception(exc)
    
          self.response = self.finalize_response(request, response, *args, **kwargs)
          return self.response
  • initialize_request 方法json

    def initialize_request(self, request, *args, **kwargs):
          """
          Returns the initial request object.
          """
          parser_context = self.get_parser_context(request)
    
          return Request(
              request,
              parsers=self.get_parsers(),
              authenticators=self.get_authenticators(),
              negotiator=self.get_content_negotiator(),
              parser_context=parser_context
          )
  • initial方法(內部調用認證,權限和頻率)api

    def initial(self, request, *args, **kwargs):
          """
          Runs anything that needs to occur prior to calling the method handler.
          """
          self.format_kwarg = self.get_format_suffix(**kwargs)
    
          # Perform content negotiation and store the accepted info on the request
          neg = self.perform_content_negotiation(request)
          request.accepted_renderer, request.accepted_media_type = neg
    
          # Determine the API version, if versioning is in use.
          version, scheme = self.determine_version(request, *args, **kwargs)
          request.version, request.versioning_scheme = version, scheme
    
          # Ensure that the incoming request is permitted
          self.perform_authentication(request)
          self.check_permissions(request)
          self.check_throttles(request)

    三 djangorestframework的Request對象簡單介紹

序列化組件

序列化組件之 serializers.Serializer

  1. 導入:
from rest_framework import serializers
  1. 寫一個類,(名字任意),繼承 serializers.Serializer
class BookSer(serializers.Serializer):
     nid=serializers.IntegerField()
     name3=serializers.CharField(source='name')
     price=serializers.CharField()
     # publish_date = serializers.DateField()
     publish_date = serializers.CharField()
     # publish=serializers.CharField(source='publish.email')
     publish=serializers.CharField(source='publish.name')
     #指定models內的方法
     xxx=serializers.CharField(source='test')
     # authors=serializers.CharField(source='authors.all')
      
     # SerializerMethodField,能夠寫一個方法方法名叫:get_字段名字,方法返回值,會賦給authors  固定用法, get_字段名字
     aa=serializers.SerializerMethodField()
     # def get_authors(self,obj):
     #     authors=obj.authors.all()
     #     # ll=[ author.name for author in authors]
     #     ll=[ {'name':author.name,'age':author.age} for author in authors]
     #     return ll
     def get_aa(self, obj):
         authors = obj.authors.all()
         # ll=[ author.name for author in authors]
         #能夠繼續去關聯查詢
         ser=AuthorSer(authors,many=True)
         return ser.data
         
  class AuthorSer(serializers.Serializer):
      id=serializers.IntegerField(source='nid')
      age=serializers.CharField()
      name=serializers.CharField()

modelssession

class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField(auto_now_add=True)
        publish =models.ForeignKey(to='Publish',
        to_field='nid',
        on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        def test(self):
            return 'ttttttt'
        def __str__(self):
            return self.name
  1. 若是不指定source,字段名,必須跟數據庫列名一致.列名及數據庫字段名稱
  2. source 既能夠指定數據屬性,又能夠指定方法屬性,能夠寫(publish.name)
  3. 使用:

1.查詢出要序列化的數據: python books = models.Boos.object.all()
2.ret = myserial.BoosSer(books,many=True)多條(queryset對象),必須指定many = True
3.ret = myserial.BoosSer(books,many=False)多條(queryset對象),必須指定many = Falseapp

  1. aa=serializers.SerializerMethodField()
  • 必須配套一個方法(get_aa(self,obj)),方法返回結果,會賦值給aa
  • 在方法內部,能夠繼續使用序列化組件iview

    序列化組件之 serializers.ModelSerializer

  • 用戶同Serializer
  • 不一樣點 : serializers.ModelSerializer 能夠直接在views save存儲.! serializers.Serializer 須要本身去寫save方法

    from rest_framework import serializers
        class BookSer(serializers.ModelSerializer):
          class Meta:
              # 指定要序列號的表模型是book
              model=models.Book
              #查詢全部的列
              fields='__all__'
                #也能夠傳列表,指定取幾個
                #fields=['name','authors','publish']
              #除了nid都查
              exclude=['nid']
              #查詢的深度,若是有關聯的表,會自動關聯查詢,深度爲1的全部數據
              depth=1
                #fields和exclude不能同時用
              # depth指定深度,我的建議最多用3

序列化組件的局部校驗 和 全局校驗

  • 局部校驗 validate_ + '校驗字段的名稱'
name=serializers.CharField(error_messages={'required':'該字段必填'})
     def validate_name(self,value):
         if value.startswith('sb'):
             raise ValidationError('不能以sb開頭')
         else:
             return value
  • 全局校驗 def validate(self,value)
def validate(self,value):
         print(type(value))
         print(value)
         name=value.get('name')
         price=value.get('price')
         if name!=price:
             raise ValidationError('書名和價格不相等')
         else:
    
             return value

-參考過程-

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
# Create your views here.

import json

# def books(request):
#
#     ll=[{'name':'python全站開發','price':20},{'name':'linux','price':30}]
#
#     # return HttpResponse(json.dumps(ll))
#     return JsonResponse(ll,safe=False,json_dumps_params={'ensure_ascii':False})
# 原聲cbv執行流程---》as_view----》dispatch---》相應到具體的函數
# from django.views import View
# class Book(View):
#     def get(self,reuquest):
#         # reuquest.method
#         return HttpResponse('get')
#     def post(self,request):
#         return HttpResponse('post')


from rest_framework.views import APIView

# class Book(APIView):
#     def get(self,request):
#         # 拿原來的request對象
#         # request._request
#         # print(request.method)
#         # print(request._request.method)
#         # request.POST
#         # request.method
#         return HttpResponse('get')
#     def post(self,request):
#         print(request.method)
#         print(request._request.method)
#         print(request.POST)
#
#         # 用apiview以後,再取數據,從request.data
#         print(request.data)
#         return HttpResponse('post')

from app01 import models
# 序列化組建
# 第一種方式
# class Book(APIView):
#     def get(self,request):
#         response={'status':100,'msg':None}
#         books=models.Book.objects.all()
#         # ll=[]
#         # for book in books:
#         #     ll.append({'name':book.name,''})
#         ll=[ {'name':book.name,'price':book.price} for book in books]
#         response['msg']='查詢成功'
#         response['data']=ll
#         return JsonResponse(response,safe=False)
#
#         # return HttpResponse('get')
#     def post(self,request):
#
#         return HttpResponse('post')

# 第二種方式,用django子自帶序列化組件
from django.core import serializers


# class Book(APIView):
#     def get(self,request):
#         # response={'status':100,'msg':None}
#         books = models.Book.objects.all()
#         ret = serializers.serialize("json", books)
#         return HttpResponse(ret)
#
#         # return HttpResponse('get')
#     def post(self,request):
#
#         return HttpResponse('post')

# 第三種方式。drf的序列化組件


class MyResponse():
    def __init__(self):
        self.status = 100
        self.msg = None

    @property
    def get_dic(self):
        return self.__dict__

URls
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>\d+)/', views.BookDetail.as_view()),
    
# 視圖類******
# 方式一
# from app01 import myserial
# class Book(APIView):
#     queryset=models.Book.objects.all()
#     serializer_class=myserial.BookSer
#     def get(self,request):
#         response=MyResponse()
#         # 多條
#         # books = models.Book.objects.all()
#         # ret=myserial.BookSer(books,many=True)
#         # 一條
#         book = self.queryset
#         # ret = myserial.BookSer(book, many=False)
#         ret = self.serializer_class(instance=book, many=True)
#         response.msg='查詢成功'
#         response.data=ret.data
#         return JsonResponse(response.get_dic,safe=False)
#
#         # return HttpResponse('get')
#     def post(self,request):
#         # print(request.data)
#         ser=myserial.BookSer(data=request.data)
#         if ser.is_valid():
#             ser.save()
#             return HttpResponse('成功')
#         else:
#             print(ser.errors)
#
#             return JsonResponse(ser.errors)
#
# class BookDetail(APIView):
#     def get(self,request,id):
#         response=MyResponse()
#         ret=models.Book.objects.filter(pk=id).first()
#         ser=myserial.BookSer(instance=ret,many=False)
#         response.msg='查詢成功'
#         response.data=ser.data
#         return JsonResponse(response.get_dic,safe=False)
#
#     def put(self,request,id):
#         # 修改
#         response=MyResponse()
#         book=models.Book.objects.filter(pk=id).first()
#         ser=myserial.BookSer(instance=book,data=request.data)
#         if ser.is_valid():
#             # 能夠新增,能夠修改
#             ser.save()
#             print(ser.data)
#             print(type(ser.instance))
#             response.msg='修改爲功'
#             response.data=ser.data
#
#         else:
#             response.msg = '修改失敗'
#             response.status = 101
#             response.data=ser.errors
#         return JsonResponse(response.get_dic,safe=False)
#
#     def delete(self,request,id):
#         ret=models.Book.objects.filter(pk=id).delete()
#         return HttpResponse('刪除成功')
# 方式二
# from app01 import myserial
#
# from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin
# from rest_framework.generics import GenericAPIView
#
# class Book(GenericAPIView,ListModelMixin,CreateModelMixin):
#     queryset=models.Book.objects.all()
#     serializer_class=myserial.BookSer
#     def get(self,request,*args, **kwargs):
#         return self.list(self,request,*args, **kwargs)
#
#         # return HttpResponse('get')
#     def post(self,request,*args, **kwargs):
#         return self.create(request,*args, **kwargs)
#
# class BookDetail(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
#     queryset=models.Book
#     serializer_class=myserial.BookSer
#     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)


# class Author(GenericAPIView,ListModelMixin):
#     queryset=models.Author.objects.all()
#     serializer_class=myserial.AuthorSer
#     def get(self,request,*args, **kwargs):
#         return self.list(self,request,*args, **kwargs)

-----

# 第三種方式
URLS
url(r'^books/$', views.BookView.as_view({'get':'list','post':'create'})),
url(r'^books/(?P<pk>\d+)/', views.BookView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
# class BookView(ListCreateAPIView):
#     queryset=models.Book.objects.all()
#     serializer_class=myserial.BookSer
#
# class BookDetailView(RetrieveUpdateDestroyAPIView):
#     queryset=models.Book.objects.all()
#     serializer_class=myserial.BookSer

___

# 第四種
from rest_framework.viewsets import ModelViewSet

# class BookView(ModelViewSet):
#     queryset=models.Book.objects.all()
#     serializer_class=myserial.BookSer
#
# class AuthorView(ModelViewSet):
#     queryset=models.Author.objects.all()
#     serializer_class=myserial.AuthorSer


----

URLS
url(r'^books/$', views.BookView.as_view({'get':'get_all'})),
url(r'^books/(?P<pk>\d+)/', views.BookView.as_view({'get':'get_one'})),

# 項目中用的最多
# from rest_framework.viewsets import ViewSetMixin
# class BookView(ViewSetMixin,APIView):
#
#     def get_all(self,request):
#         return HttpResponse('返回全部')
#     def get_one(self,request,pk):
#         return HttpResponse('返回一條')


# from app01 import myserial
# class List():
#     def list(self,request,*args,**kwargs):
#         response=MyResponse()
#         # 多條
#         # books = models.Book.objects.all()
#         # ret=myserial.BookSer(books,many=True)
#         # 一條
#         book = models.Book.objects.all()
#         # ret = myserial.BookSer(book, many=False)
#         ret = self.serializer_class(instance=book, many=True)
#         response.msg='查詢成功'
#         response.data=ret.data
#         return JsonResponse(response.get_dic,safe=False)
#

re_path('students/$', views.Stu.as_view({'get':'get_all'})),
re_path('students/(?P<pk>\d+)/$', views.StuDetail.as_view({'get':'get_one'})),

class Stu(ViewSetMixin,APIView):

    def get_all(self,request):
        response = MyResponse()
        strs = models.Student.objects.all()
        ret = myserial.StrSer(instance=strs,many=True)
        response.msg = '查詢成功'
        response.data = ret.data
        return JsonResponse(response.get_dic,safe=False)


class StuDetail(ViewSetMixin,APIView):

    def get_one(self,request,pk):
        response = MyResponse()
        strs = models.Student.objects.filter(pk=pk).first()
        ret = myserial.StrSer(instance=strs,many=False)
        response.msg = '查詢成功'
        response.data = ret.data
        return JsonResponse(response.get_dic,safe=False)
相關文章
相關標籤/搜索