DRF learning and related source code reading

1.http Request Protocol

1.cbv
    django.vuews import View
    classs LoginView(View):
        def get(self,requset):
            pass
2.classmethod $ classonlymethod
3.getattr hasattr setattr
4.self定位
    - 始终代表调用者本身
5.http请求协议:就是约定成俗的规范,解析数据的规范
6.form enctype 
    解析参数的格式
7.  javascript object {name: "alex"} ===>json转换的方式
    7.1 data:Json.stringify({name: "alex", age: 18}) ==>json.dumps(data)
        JSON.parse(data) ===> json.loads()
    

Today's details:

1. djaong-restframework

​ 1.1 ApiVIew

urlpatterns = [
    re_path('^course/$', views.CourseView.as_view()),
]
url_mapping = {
    "login": "LoginView"
}
第一步:从as_view向里看
rest-framework如何对django的view进行扩展的呢

1.2 parser component

1.3 serialization component

1.4 authentication component

1.5 Permissions components

1.6 Frequency Components

1.7 url controller components

1.8 paging component

1.9 Response assembly

Today content summary:

  • Knowledge review summary

    • What is programming

      Algorithms + Data Structure

    • What is the rest

      https://www.jd.com #通过url拿到数据
      2.1原始url
          127.0.0.1:8001/books/id/    
          127.0.0.1:8001/books/?name=""
          127.0.0.1:8001/books/delet/id/      
          这种url方式使得接口看起来多而且杂,维护不方便    
      url用来唯一定位资源,用http请求方式来区分用户对数据的操作方式  
      2.2rest url
          1.url设置规范
              GET:127.0.0.1:8001/books/    # 获取所有数据    
              GET:127.0.0.1:8001/books/id/ # 获取单挑数据
              POST:127.0.0.1:8001/books/   # 增加数据   
              DELETE:127.0.0.1:8001/books/id/ # 删除数据
              UPDATE:127.0.0.1:8001/books/id/ # 更改数据     
          2.数据响应规范
              GET:127.0.0.1:8001/books/    # 获取所有数据    返回[{},  ,]
              GET:127.0.0.1:8001/books/id/ # 获取单挑数据    返回{}单条数据
              POST:127.0.0.1:8001/books/   # 增加数据       返回{}添加成功
              DELETE:127.0.0.1:8001/books/id/ # 删除数据    返回‘’返回空
              put/UPDATE:127.0.0.1:8001/books/id/ # 更改数据    返回更新后的完整数据
          3.错误处理
              {"error":"message"}
    • cbv

    • classmethod & classonly method

    • getattr hasattr setattr

      Dynamic properties of the object to be operated

    • self positioning

      It is always positioned themselves

    • Http request data protocol

      Backend data request to resolve what way

    • From which three kinds of forms request protocol enctype

      urlencoded, multi-formdata, text/plain

    • JavaScript object serialized to json

      object ===>json(json.stringify) json====>object(JSON.parse())




class LoginView(ApiView):
    def post(self,request):
        data = request.data  #新的request对象
        return

class ApiVIew(View):

    @classmethod
    def as_view(self, request):
        pass 
        super(ApiView,self).as_view(**initkwargs)
    def dispatch():
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
parser_context = self.get_parser_context(request)

return Request( 
    request,  # 原生reqeust
    parsers=self.get_parsers(),  # get_parsers()
    authenticators=self.get_authenticators(),
    negotiator=self.get_content_negotiator(),
    parser_context=parser_context
)

ApiView.py中的
def get_parsers(self):
    """
        Instantiates and returns the list of parsers that this view can use.
        """
    return [parser() for parser in self.parser_classes]
from rest_framework.request import Request
data = request.data  #新的request对象
从reqeust中.出来的,所以其Request中找这个属性
3. parser source code process:
__getattr__在属性未找到的时候
第一步:执行as_view()
第二步:自己写的里面没有as_view()函数去父类中找
第三部:执行view中的as_view()方法,返回view函数
第四步:url和驶入函数之间的绑定关系建立完毕{“login”: view}等待用户请求
第五步:接收到用户请求:login,到建立好的关系里面执行对应的视图函数:view(request)
第六步:视图函数的执行结果是什么就返回给客户,self.dispatch(),self.dispatch()的执行结果
第七步:此时的self代表的是LoginView的实例对象
第八步:开始找dispatch方法,self里面没有,LoginVIew里面也咩有,在ApiView中
第九步:开始执行apiview中的dispatch方法
第十步:在最后找到http方法(get,post,put,delete),根据请求的类型查找(reqeust.method.lower())
第十一步:执行第十步找到的方法,开始执行找到的方法self.get()代表的是LoginView的实例化对象
    11.1 假设接受到的时候POST请求,执行reuqest。data
    11.2 分析结果,所有的解析工作都是在request。data里面实现的,且data是一个方法(被属性化之后的)
    11.3 拿取data
         @property
         def data(self):
            if not _hasattr(self, '_full_data'):
                self._load_data_and_files()
            return self._full_data
    11.4 执行_load_data_and_files()
    11.5 parser = self.negotiator.select_parser(self, self.parsers)
        11.5.1parsed = parser.parse(stream, media_type, self.parser_context)
        11.5.2 self.get_parses()
             return [parser() for parser in self.parser_classes]
        11.5.3 parser_classes = api_settings.DEFAULT_PARSER_CLASSES
        11.5.4 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
        11.5.6 APISettings是一个类
        11.5.7 找不到parser_classes = api_settings.DEFAULT_PARSER_CLASSES
            的时候就去__getattr__里面找
        11.5.8 __getattr__里面有这么一句话 val = self.user_settings[attr]
            @property
            def user_settings(self):
                if not hasattr(self, '_user_settings'):
                    self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
                return self._user_settings
        11.5.9 首先找自己的settiongs,之后找rest_framework的settings
        
    11.6 得到self._data = parsed.data
    11.7 DRF将self.date = self._data
    11.8 reqeust.data
第十二部:在loginView里面找到对应的方法,执行该方法,最后返回给用户
  • All functions are in DRF as_view () and dispatch () inside rewritten
  • The parser component dispatch method in which rewrite, Request object is repackaged in particular it is
class ParseJson():

    pass
class ParseForm():
    data = request.body.decode('utf-8')
    data.split("&")
    return data
def select_parse(request,ParseJson, ParseForm):
    return 
Knowledge Point Review:

1.cbv

2.classmethod & classonlymethod

from django.utils.decorators import classonlymethod
class JinJa(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def sleeping(cls):
        print("sleeping")

    @classonlymethod
    def shui(cls):
        print("shui_jiao")
装饰器在类加载的时候执行。        

3.getattr,hasattr,setattr

4.self positioning

谁调用就是谁。

5.http Request Protocol

6.form enctype

7.JavaScriot object {name: "pizza"} =====>json转换

# 可以建立一个apps文件夹,将每个app放入其中
APPS_DIR= os.path.join(BASE_DIR, "apps")
sys.path.append(APPS_DIR)

2.view the request process
    1.通过as_view
        def view(request, *args, **kwargs):
            # 实例化一个对象,对象名称为self,self是cls的对象,谁调用cls
            # cls就是谁(当前调用cls的是BookVIew)
            # 所以,此时的self就是BookView的实例化对象
            self = cls(**initkwargs) 
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *args, **kwargs)
        返回函数 return self.dispatch(request, *args, **kwargs)
    2.执行dispatch方法
    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对象指向原始的request对象
        # 给self这个实例化对象赋值:原始的request(下面这行代码对request进行加工)
        request = self.initialize_request(request, *args, **kwargs)
        # 重新对request进行赋值
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            self.initial(request, *args, **kwargs)
            # 通过请求的方式进行路由匹配,如果早安全的方式里就尝试获取执行的函数
            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
4.rest use
1.from rest_framework.views import APIVIew
2.继承VPIView
    class HomeView(APIVIew):
        def get(self):
            pass
3.url.py
    from django.urls import path,include,re_path
    urlpatterns = [
        re_path('^course/$', views.CourseView.as_view()),
    ]
4.def post(self,request):
    origin_data = request.data
    ......
    return HttpResonse({})
源码剖析:request.data是从哪里来的?
    1.dispatch方式中对request进行重新构造
        request = self.initialize_request(request, *args, **kwargs)
        
        def initialize_request(self, request, *args, **kwargs):
            parser_context = self.get_parser_context(request)
            return Request(
                request,
                parsers=self.get_parsers(),
            )
        # 1.1自己里面没有定义
        def __init__(self, request, parsers=None, authenticators=None,
                     negotiator=None, parser_context=None):
            self._request = request
            self.parsers = parsers or ()   # self.get_parsers()的结构
        # 1.2还是在Requet里面找
        @property
        def data(self):
            if not _hasattr(self, '_full_data'):
                self._load_data_and_files()
            return self._full_data
        # 1.3_load_data_and_files()
        def _load_data_and_files(self):
            if not _hasattr(self, '_data'):
                self._data, self._files = self._parse()  # 执行执行这个方法
                if self._files:
                    self._full_data = self._data.copy()
                    self._full_data.update(self._files)
                else:
                if is_form_media_type(self.content_type):
                    self._request._post = self.POST
                    self._request._files = self.FILES
        # 1.4 self._parse()
        def _parse(self):
            parser = self.negotiator.select_parser(self, self.parsers) # 解析器对象
            parsed = parser.parse(stream, media_type, self.parser_context) # 解析之后的结果
            return (parsed.data, parsed.files)
        # 1.5  self.parsers  # 获取解析器
        def get_parsers(self): 
            return [parser() for parser in self.parser_classes]
        # 1.6   self.parser_classes 一个属性
        class APIView(View):
            parser_classes = api_settings.DEFAULT_PARSER_CLASSES
            
        api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
        
        # 因为找不到所以执行__getattr__方法
        def __getattr__(self, attr):
            try:               
                val = self.user_settings[attr] # 我们项目的settings文件中的默认参数
            except KeyError:
                # 没找到就去找rest的settings获取默认的参数
                val = self.defaults[attr]

            # Coerce import strings into classes
            if attr in self.import_strings:
                val = perform_import(val, attr) # 这里的到的解析器类对象列表

            # Cache the result
            self._cached_attrs.add(attr)
            setattr(self, attr, val)
            return val  # 这里返回的就是解析器列表
        # 1.7 perform_import(val, "DEFAULT_PARSER_CLASSES") 
        # val是这个:
             'DEFAULT_PARSER_CLASSES': [
                    'rest_framework.parsers.JSONParser',
                    'rest_framework.parsers.FormParser',
                    'rest_framework.parsers.MultiPartParser'
                ],
        def perform_import(val, setting_name)
            if val is None:
                return None
            elif isinstance(val, str):
                return import_from_string(val, setting_name)
            elif isinstance(val, (list, tuple)):
                return [import_from_string(item, setting_name) for item in val]
            return val
        # 1.8 
        def import_from_string(dotted_path):
            try:
                module_path, class_name = dotted_path.rsplit('.', 1)
            except ValueError as err:
                raise ImportError("%s doesn't look like a module path" % dotted_path) from err

            module = import_module(module_path)  # 动态导包进行包的获取

            try:
                return getattr(module, class_name)

super方法的解释
    1.不使用super我们可以通过以下方式
    class JinJa:
        def __init__(self):
            print("jinja is a parse")
    class To:
        def __init__(self):
            To.__init__(self,)
    2. 使用super方式
        2.1 python2
        class JinJa:
            def __init__(self):
                print("jinja is a parse")
        class To:
            def __init__(self):
                super(TO,self).__init__(*args, **kwargs)# super(参数必须传递,self)有参数必须传递参数
        2.2 python3
        class JinJa:
            def __init__(self):
                print("jinja is a parse")
        class To:
            def __init__(self):
                super().__init__(*args, **kwargs)# 有参数必须传递参数

* Dynamic on package
import importlib
moudle = input("请输入要导入的模块:")
moudle = importlib.import_module(module)
# 通过字符串方式引入模块
Knowledge Point Review:

1. ternary operator: "alex" if a else "wusir"

2. List comprehensions

3.__getattr__

4.djaong settiong file search order global_settings

5. Dynamic import

6.Django virgin

The serializer
# django原生的serializer
from django.core.serializers import serialize
class CourseView(APIView):
    # 这是局部的解析器,自定制的地方
    parser_classes = [FormParser, JSONParser]
        def get(self, request):
        course_list = list()
        cour = Course.objects.all()
        for course in cour:
            course_dict = {
                "course_name": course.course_name,
                "description": course.description,
            }
            course_list.append(course_dict)
        ser_data = serialize("json", cour)
        print(ser_data)
        # ensure_ascii显示中文
        return HttpResponse(json.dumps(course_list, ensure_ascii=False))
# 1.开始使用序列化类
    - 导入模块
    - 建立一个序列化类
    - 获取queryset
    - 开始序列化
    - 获取序列化后的数据,返回给客户端
class BookSerializer(serializers.Serializer):
    # nid = serializers.IntegerField()
    title = serializers.CharField(max_length=32)
    price = serializers.DecimalField(max_digits=10, decimal_places=2)
    # 可以使用source字段覆盖当前的字段的显示,read_only只读字段
    publish = serializers.CharField(max_length=32)
    publish_name = serializers.CharField(read_only=True, max_length=32, source="publish.name")
    city_name = serializers.CharField(read_only=True, max_length=32, source="publish.city")
    # authors = serializers.CharField(max_length=32)
    authors = serializers.SerializerMethodField()

    # instance是这次循环的书籍对象(额外字段都可以)
    def get_authors(self, instance):
        author_list = []
        for author in instance.authors.all():
            author_list.append(author.name)
        return author_list

    # 如果用的是Serializer,这里需要你自己写create方法
    def create(self, validated_data):
        validated_data["publish_id"] = validated_data.pop('publish')
        book_obj = Book.objects.create(**validated_data)
        return book_obj


class BookView(APIView):
    def get(self, request):
        # 获取queryset
        origin_data = Book.objects.all()
        # 将获取到的数据传入序列化类,数据多条是many=True
        ser_data = BookSerializer(origin_data, many=True)
        return Response(ser_data.data)

    def post(self, request):
        client_data = request.data
        ser_data = BookSerializer(data=client_data)
        if ser_data.is_valid():
            book = ser_data.save()
            authors = Author.objects.filter(nid__in=request.data["authors"])
            book.authors.add(*authors)
            return Response(ser_data.data)
        else:
            return Response(ser_data.errors)
Knowledge Point Review:
1.解析器组件
    - 解析器组件是用来解析用户请求的数据的(application/json), content-type
    - 必须继承APIView
    - request.data触发解析
2.序列化组件
    2.1 Django自带的serializer
        2.1.1 from django.serializer import serialize
        2.1.2 Origin_data = Book.object.all()
        2.1.3 serializer_data = serialzie("json", origin_data)
    2.2 DRF的序列组件
        - get 接口设计
            2.2.1 from rest_framwork import serializers
            2.2.2 创建一个序列化类
                class BookSerialzier(serializer.Serializer):
                    publish_name = serializer(read_obly=True, source="publish.name")
                    authors_list = serialzier.SerializerMethodField()

                    def get_authors_list(self, instance):
                        pass
            2.2.3 开始序列化
                origin_data = Book.objects.all()
                ser_data = BookSerializer(data=origin_data, many=true)
                return Response(ser_data.data)
         - post接口设计
            总结:
                1.serializers.Serialzier无法插入数据,需要自己实现create
                2.字段太多,不能自动序列化
         - get 单条数据接口设计
            1.定义url
            2.获取数据对象
            3.开始序列化:ser_data = BookSerializer(instance=book_obj)
            4.返回数据: return Response(ser_data.data)
         - delete 
         - put
            1.定义url
            2.获取数据对象
                2.1 book_obj = Book.objects.get(pk=1)
            3.开始序列化(验证数据,save(0))
                3.1ser_data = BookSerializer(instance=book_obj, many=False)
            4.返回数据: return Response(ser_data.data)
                
serializers.py
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"
        extra_kwargs = {
            # "publish": {"write_only": True},
            # "authors": {"write_only": True},
        }
    publish_name = serializers.CharField(read_only=True, max_length=32, source="publish.name")
    city_name = serializers.CharField(read_only=True, max_length=32, source="publish.city")
    # authors = serializers.SerializerMethodField()

    # def get_authors(self, instance):
    #     author_list = []
    #     for author in instance.authors.all():
    #         author_list.append(author.name)
    #     return author_list
6. Today's content:
今日内容:
    1.接口设计
    2.视图组件
        - 试图组件是用来优化接口逻辑的
前提提要:
    - 多继承
今日详细:
    - 使用试图组件进行接口优化
        - 使用试图组件mixin进行接口逻辑优化
            from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin
            from rest_framework.generics import GenericAPIView
            
            class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
            class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
                  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)
            注意:单条数据操作的url是这样的re_path('^book/(?P<pk>\d+)/$', views.BookFilterView.as_view()),
            class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
                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 BookFilterView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
                queryset = Book.objects.all()
                serializer_class = BookSerializer

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

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

                def put(self, request, *args, **kwargs):
                    return self.update(request, *args, **kwargs)
        - 使用试图组件的view进行接口逻辑优化
            - 导入模块
            from rest_framework import generic
            - 写视图类
            class BookView(generics.ListCreateAPIView):
                queryset = Book.objects.all()
                serializer_class = BookSerializer


            class BookFilterView(generics.RetrieveUpdateDestroyAPIView):
                queryset = Book.objects.all()
                serializer_class = BookSerializer
        
        - 使用viewset优化接口逻辑
            - 编写url
            urlpatterns = [
                re_path('^book/$', views.BookView.as_view(actions={
                    "get": "list",
                    "post": "create"
                })),
                re_path('^book/(?P<pk>\d+)/$', views.BookView.as_view({
                    "get": "retrieve",
                    "put": "update",
                    "delete": "destroy"
                })),
                ]
            - 导入模块
                from rest_framework.viewset import ModelViewSet
            - 设计视图类
                class BookView(ModelViewSet):
                    queryset = Book.objects.all()
                    serializer_class = BookSerializer
Knowledge Point Review:
1.继续设计接口
    1.1 post接口设计
        - 如果使用serializer.Serialiezer会有如下问题:
            1.需要手动插入数据(必须自定义create方法)
            2.手动序列化需要的字段
        - 为了解决上面的问题,我们建议使用serializer.ModelSerializer
            class BookSerializer(serializers.ModelSerializer):
                class Meta:
                    model = Book
                    fields = "__all__"
                    extra_kwargs = {
                        # "publish": {"write_only": True},
                        # "authors": {"write_only": True},
                    }
                publish_name = serializers.CharField(read_only=True, max_length=32, source="publish.name")
                city_name = serializers.CharField(read_only=True, max_length=32, source="publish.city")
                authors = serializers.SerializerMethodField()

                def get_authors(self, instance):
                     author_list = []
                     for author in instance.authors.all():
                         author_list.append(author.name)
                     return author_list
    1.2 delete接口设计
        class BookView(ApiView):
            def delete(self, request, id):
                obj = Book.objects.get(pk=id).delete()
                reutrn Response()
    1.3 put接口设计
        class BooKFilterView(APIVIew):
            def put(self,reqeust,id):
                data = request.data
                book_obj = Book.objects.get(pk=id)
                
                ser_data = BookSerializer(data=request.data, instance=book_obj,many=Flase)
                
                if ser_data.is_valid():
                    ser_data.save()
                    return Response(res_data.data)
                else:
                    return Response(res_data.errors)
    1.4 get获取单条
        class BooKFilterView(APIVIew):
            
            def get(self,reqeust,id):
                book_obj = Book.objects.get(pk=id)
                ser_data = BookSerializer(instance=book_obj,many=Flase)
                return Response(ser_data.data)
2.视图组件(mixin, genericview, viewset)
    视图组件是用来优化接口逻辑的
    2.1 使用mixin的使用
        - 导入 
            from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin,RetireveModelMixin
            from rest_framework.genericview import GenericAPIView
        - 设计视图类
            class BooKView(ListModelMixin, CreateModelMixin, GenericAPIView):
                serializer_classes = BooKSerialzier
                queryset = Book.objects.all()
                
                def get(self, request, *args, **kwargs):
                    return self.list(request, *args, **kwargs)
                def post(self, request, *args, **kwargs):
                    return self.create(request, *args, **kwargs)
    2.2 mixin源码剖析
to sum up:
day:1
    - 1.什么是编程
    - 2.什么是rest
    - 3.BS架构中,客户端通过url来访问客户端的资源(数据)
    - 4.传统的url中设计里面包含动词(理论上来说,可以实现业务需求)
    - 5.rest
        url是唯一定位资源,http请求方式描述用户行为
        GET:127.0.0.1:8001/books/    # 获取所有数据    
        GET:127.0.0.1:8001/books/id/ # 获取单挑数据
        POST:127.0.0.1:8001/books/   # 增加数据   
        DELETE:127.0.0.1:8001/books/id/ # 删除数据
        UPDATE:127.0.0.1:8001/books/id/ # 更改数据  
        返回规范:
        GET:127.0.0.1:8001/books/    # 获取所有数据    返回[{},  ,]
        GET:127.0.0.1:8001/books/id/ # 获取单挑数据    返回{}单条数据
        POST:127.0.0.1:8001/books/   # 增加数据       返回{}添加成功
        DELETE:127.0.0.1:8001/books/id/ # 删除数据    返回‘’返回空
        put/UPDATE:127.0.0.1:8001/books/id/ # 更改数据    返回更新后的完整数据
        错误处理
        {"error":"error_message"}
     - 6.CBV
        - 定义view.py 
            from django.views import View
            class BookView(View):
                
                def get(self. request):
                    pass
                
                def post(self, request):
                    pass
        - 定义url.py
            from django.urls import re_path
            
            urlpatterns = [
                re_path("`book/$", views.BookVIew.as_view()),
            ]
            
            @classonlymethod
            def as_view(cls, *arg, **kwargs):
                def view(request):
                    self = cls(**args)
                    return self.dispath()
                return view
            
            def dispatch(self,request):
                if hasattr(self, self.method.lower(),):
                    handler = getattr(self, self.method.lower())
                else:
                    raise
                return handler(reqeust, *args, **kwargs)
    - 7.django restframework 
        - 本质上是一个django app 用来帮助我们更快的开发出符合rest规范的web app
        - pip install django
        - pip install djangorestframework
        - 定义views.py 
            from rest_framework.views import APIVIew
            class ApiView(view);
                @classonlymethod
                def as_view(cls, request, *args, *8kwargs);
                    view = super(APIView, cls).as_view()
                    return view
                def dispatch(self,request):
                    if hasattr(self, self.method.lower(),):
                        handler = getattr(self, self.method.lower())
                    else:
                        raise
                    return handler(reqeust, *args, **kwargs)
            class BookView(APIView):
                def get(self, reqeust):
                    pass
        - 定义url.py
            from django.urls import re_path
            
            url_parttrens = [
                re_path("books/`$", BookView.as_view()),
            ]
    - 8.drf解析器
        - 定义views.py
            from django.https import  JsonResponse 
            from rest_framework.views import APIView
            from rest_framework.reqeust import Request
            
            class Request(request):
                
                def __init__(self, parsers=get_parser()):pass
                
                def _parse(self):
                    parser = self.negotiator.select_parser(self, self.parsers)
                    parsed = parser.parse(stream, media_type, self.parser_context)
                    
                    return parsed.data, parsed
                .files
                
                def _laod_data_and_file(self)
                    self.data, self.files = self._parse()
                    self._full_data = self.data
                    
                @proparty
                def data(self):
                    if not hasattr(self, "full_data"):
                        self._laod_data_and_files()
                    return self._full_data
            
            class APIVIew(View):
                
                parser_classes = apisettings.DEFAULT_PARSERS_CLASSES
                
                def get_parsers(self):
                    return [parser() for parsr in self.parser_classes]
                
                def initialize_request(self,request):
                    return Request(request,
                            parser = self.get_parsers())
                
                def dispatch(self, request):
                    request = self.initialize_request(request, *args, **kwargs)
                    self.request = request
                    return response()
                
            class BookView(APIVIew):
                def get(self. request):
                    pass
                
                def post(self, request):
                    request.data
                    return JsonResponse()
                
day2:
    1.解析器组件
    2.序列化组件
        2.1 django原生的序列化
            - 导入
            from django.core serialziers import serialize
            class BooVIew(APIVIew):
                def get(self, request):
                    books = Book.object.all()
                    ser_data = serialzie("json", books)
                    return HttpResponse(ser_data)
        2.2 drf序列化组件
            - 导入
            from rest_framework import serialzers
            - 定义序列化类
            class BooKSerializer(serializers.Serializer):
                title = serializers.Charfield(max_length=32)
                price = serializers.DecimalField()
                publish = serialziers.CahrField(max_Lenght=32)
                publish_name = serializers.CharField(max_lenght=32, source="publish.name", read_only=True)
                authors_list = serializers.SerializerMethodField()
                
                def get_authors_lsit(self, instance):
                    authors = list()
                    for author in instance.authors():
                        authors.append(author.name)
                    return authors
                def create(self, verified_data):
                    pass
                
                def updata(self, verified_data):
                    pass
                    
            - 定义view.py
            class BoosView(APIView):
                def get(self, request):
                    books = Book.object.all()
                    ser_data =  BooKserialzier(books, many=True)
                    reutnr Response(ser_data.data)
        2.3 通过drf的序列化组件进行接口设计
        2.4 通过drf的序列化组件进行POST接口设计
            - 定义view。py
                class BoosVIew(APIVIew);
                    def post(self, request):
                        data = request.data
                        ser_data = BooKSerialzier(data=data, many=False)
                        if ser_data.is_valid():
                            # BooKSerialzier没有实现写入操作即就是create方法
                            ser_data.save()
                            reutnr Response(ser_data.data)
                        else:
                            reutnr Response(ser_data.errors)
                    def put(self, request, id):
                        data = request.data
                        book_obj = Book.objects.get(pk=id)
                        ser_data = BooKSerialzier(instance=book_obj,data=data, many=False)
                        if ser_data.is_valid():
                            ser_data.save()
                            reutnr Response(ser_data.data)
                        else:
                            reutnr Response(ser_data.errors)
day3:
    1.通过drf的序列化组件进行put接口设计
    def put(self, request, id):
        data = request.data
        book_obj = Book.objects.get(pk=id)
        ser_data = BooKSerialzier(instance=book_obj,data=data, many=False)
        if ser_data.is_valid():
            ser_data.save()
            reutnr Response(ser_data.data)
            else:
                reutnr Response(ser_data.errors)
    2.通过drf的序列化组件进行delete接口设计
    3.通过drf的序列化组件进行get接口设计
    4.试图组件
        - 视图组件是用来优化接口逻辑的
        4.1 mixins
            - 导入
                from rest_framework.mixins import (ListModelMixin,                      
                                                   CreateModelMixin,
                                                   UpdateModelMixin, 
                                                   RetrieveModelMixin,
                                                   DestoryModelMixin)
                from rest_framework.generics import GenericAPIView
            - 定义序列化类
            - urls.py
                re_path('^book/$', views.BookView.as_view()),
                re_path('^book/(?P<pk>\d+)/$', views.BookFilterView.as_view()),
            - 定义view.py 
                class BookView(ListModelMixin, CreateModleMixin, GenericAPIVIiew):
                    queryset = Book.objects.all()
                    serialzier_class = BookSerializer
                    
                    def get(self, request):
                        pass
                    def psot(self, request):
                        pass
                    
                class BookView(UpdateModelMixin, 
                               RetrieveModelMixin, 
                               DestoryModelMixin, 
                               GenericAPiVIew):
                    queryset = Book.objects.all()
                    serialzier_class = BookSerializer
                    
                    def get(self, request, pk):
                        return self.retrieve(request)
                    def put(self, request, pk):
                        return self.update(request)
                    def delete(self, request, pk):
                        return self.destory(request)
        4.2 genericview
            - 导入 
            from rest_framework import generics
             class BookView(generics.ListCreateAPIView):
                    queryset = Book.objects.all()
                    serialzier_class = BookSerializer
             class BookView(generics.RetrieveUpdateDestroyAPIView):
                    queryset = Book.objects.all()
                    serialzier_class = BookSerializer
        4.3 viewset
            - 导入 
            from rest_framework.viewsets import ModelViewSet
            class BookView(ModelViewSet):
                    queryset = Book.objects.all()
                    serialzier_class = BookSerializer
            - url.py
            urlpatterns = [
                re_path('^book/$', views.BookView.as_view(actions={
                    "get": "list",
                    "post": "create"
                })),
                re_path('^book/(?P<pk>\d+)/$', views.BookView.as_view({
                    "get": "retrieve",
                    "put": "update",
                    "delete": "destroy"
                })),
            ]
The frequency component authentication 7.DRF

Guess you like

Origin www.cnblogs.com/liuzhanghao/p/11976707.html