DRF Overview

A. REST

  1. What is programming?
    Combination of data structures and algorithms

  2. What is REST?
    Review ever done of library management systems, we designed the URL:

   127.0.0.1:9001/books/
   127.0.0.1:9001/get_all_books/ access to all data

127.0.0.1:9001/books/{id}/     
127.0.0.1:9001/books/{id}?method=get   访问单条数据
        
127.0.0.1:9001/books/add/
127.0.0.1:9001/books/?type=create   创建数据
        
127.0.0.1:9001/books/delete/
        
127.0.0.1:9001/books/update/   

Although the above URL defined functions can also be achieved, but because of different personal habits, etc., the same function will produce a wide variety of URL, and the response back data (including error messages, etc.) format there is no uniform standard, which resulted in around difficulties interactive end.

The resulting URL of the REST REST resources under the sole representative, http request method to distinguish between user behavior, the following is an example of REST URL design specifications comply with:

  url of design specifications:
    the GET: acquiring all the data # 127.0.0.1:9001/books/
    GET: 127.0.0.1:9001/books/{id} # of data acquisition unit
    POST: 127.0.0.1:9001/books/ # increase data
    DELETE : 127.0.0.1:9001/books/{id} # delete data
    PUT: 127.0.0.1:9001/books/{id} # modify the data
  data in response specifications:
    the GET: returns 127.0.0.1:9001/books/ # [{} , {}, {}]
    the GET: returns a single 127.0.0.1:9001/books/{id data #}} {
    the POST: 127.0.0.1:9001/books/ added successfully returned data #} {
    the DELETE: 127.0.0.1: 9001 / books / {id} # return empty ""
    the PUT: 127.0.0.1:9001/books/{id} # {} return, after recording a complete update is not a noted field
  error handling:
{ "error": " ERROR_MESSAGE "}
REST is a software architecture style, not standard, nor is technology, it just provides a set of design principles and constraints, is the most popular API design specifications for the design of web data interface.

Reference links:

http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html

http://www.scienjus.com/my-restful-api-best-practices/

So, we are going to learn Django REST Framework and REST what does it matter?

In fact, DRF (Django REST Framework) is a set of Django development, to help us better meet the design specifications of a REST Django App web application, so In essence, DRF is a Django's App.

Second, knowledge ready
before DRF study, first look at a knowledge point:

  1. CBV(class based view)
    from django.views import View
    class LoginView(View):
    def get(self, request):
    pass
    def post(self, request):
    pass
  2. 类方法 classmethod和classonlymethod
    class Person(object):
    def init(self, name, age):
    self.name = name
    self.age = age

    # Note: When the Person class is loaded, it will perform a decorator function classmethod (sleeping), and assigns the result Sleeping
    @classmethod
    DEF Sleeping (CLS): # = classmethod equivalent Sleeping (Sleeping)
    Print ( "Tom IS Sleeping")

    @classonlymethod
    def shopping(cls):
    print("Tom is shopping")

Person.sleeping () # classes directly call the class method (with @classmethod decorative)
Person.Angel () # class call the method directly (with @classonlymethod decoration)

= The Person Tom ( 'Tom', '19')
Tom.sleeping () # can directly call the object class method
Tom.shopping () # baocuo, the object can not be called by the method @classonlymethod decorated
Summary:

@classmethod (python added decorator) method may be decorated == == invoked objects and classes.
@classonlymethod (plus the Django decorator) can only be invoked == == class.

  1. Reflection, isinstance ()
    (1) getattr ()
    Description: getattr () function is called by the name of the attribute name string to find the name of the object, if found, it returns the property value of this object, if found, would returns the default

grammar:

getattr(object, name[, default])
参数:

object - Object
name - attribute string, object
default - the default return value, if the parameter is not available, there is no corresponding attribute in the trigger AttributeError
Return Value: returns the object property

(2) hasattr ()
Description: hasattr () function for determining whether the object contains the corresponding property.

grammar:

hasattr (object, name)
Parameters:

object - the object
name - string, the attribute name
Returns: If the attribute name is a name of an object exists in the object, it returns True, otherwise False.

(3) setattr ()
Description: setsttr () function corresponding to the function getsttr (), for a name attribute value of the target object set again, note that the name attributes must exist.

grammar:

setattr(object, name, value)
参数:

object - Object
name - string, object attribute
value - the attribute value
Return value: None

(4) isinstance ()
Description: isinstance () function is used to determine whether an object is a known type.

isinstence () and type () the difference:

- type () does not think that is a subclass of parent class type, without regard to inheritance.
-. Isinstence () will be considered sub-class is a parent class type, consider inheritance
To determine if the two types are the same recommended isinstence ().
syntax:

isinstence (object, classinfo)
parameters:

object - instance object
classinfo - may be directly or indirectly, class name, or basic types tuple composed of them
Return Value: If the parameter type of the two types (ClassInfo) True if the object is the same, otherwise False.

  1. self positioning
    we must be clear, self is always pointing to the caller == ==.

  2. http request protocol
    agreement is to communicate both sides to prescriptive norms, that is, the rules of analytical data

  3. enctype property sheet form, there are three protocol request
    if data submitted by the user form form, may be used to form the form enctype attribute to define data encoding protocol, the property has three values, representing three data encoding protocol:

application / x-www-form- urlencoded: This value is used a plurality of key-value pairs & symbolic links, the key-value pairs with a splice equals enctype value is the default attribute.
upload files, pictures: multipart / form-data this value is used.
text / Plain: space is converted to the +.

  1. In JavaScript object (such as: {name: 'alex'} <==> json) interconversion manner
    JSON.stringify (data) ==> corresponds to the python json.dumps ()
    the JSON.parse (Data) == > equivalent json.loads python () of
    three. Django REST Framework (DRF)
  2. Why use DRF?
    DRF In essence, it is a Django's App, with such a App, we can design a better == == comply with RESTful web application specifications. In fact, even without DRF, we can also design their own specifications in line with RESTful web application, the following example:

from django.shortcuts import HttpResponse
from django.views import View
from * import models
import json
class CourseView(View):
def get(self, request):
course_list = list()

    for course in models.Course.objects.all():
        course = {
            'course_name': course.course_name,
            'description': course.description,
        }
        course_list.append(course)

    return HttpResponse(json.dumps(course_list, ensure_ascii=False))

In the above code, we get all the course data, and based on REST specification, all resources returned to the user through the list, we can see, even without DRF, we are also able to design interface complies with RESTful specifications, and even the entire App application. However, if all interfaces are custom, there will inevitably be duplication of code, in order to improve efficiency, we recommend using a good tool, DRF is such a great tool, in addition, it can not only help us to quickly design to meet RESTful specification the interface also provides other powerful features such as authentication, permissions, and so on.

  1. When to use DRF?
    RESTful API is the most popular design specifications, if you use the Django development of web applications, then try to use the DRF, if you are using Flask, you can use the Flask-RESTful.

  2. DRF use
    DRF official documents

DRF installation

Install django

pip install django

Installation djangorestframework

pip install djangorestframework
After installation is complete, we can begin to use the DRF framework to achieve our web application framework includes the following knowledge points:

  - APIView
  - parser component
  - serialization assembly
  - assembly view
  - an authentication component
  - purview component
  - Frequency control assembly
  - paging component
  - the respective assembly
  - URL Control

  1. APIView
    introduction DRF, must introduce APIView, it is the most important, it is the basis of all of the following components, because == all == requests are to be distributed by APIView. So exactly how to distribute requests it? Want then they have to figure out this problem, we must interpret its source code, but you want to interpret the DRF APIView source code, you must first figure out the source code in django views.View class, why use view functions like call as_view (), on request different functions can be handled it?

(1) Review CBV, reading View source

urls.py code as follows:

from django.urls import path, include, re_path
from classbasedView import views
urlpatterns = [
re_path('login/$', views.LoginView.as_view())]

views.py code as follows:

Import django.views View from
class the LoginView (View):
DEF GET (Self, Request):
Pass
DEF POST (Self, Request):
Pass
the above code execution flow follows (Source Interpretation):

(1) Start django project, namely the implementation of a python manage.py runserver 127.0.0.1:8000 after
(2) begins loading the configuration file settings.py
read models.py
load views.py
loaded urls.py, execution as_view (): views.LoginView.as_view ()
(. 3) Since there is no as_view LoginView, thus performing the method as_view parent class View, View relevant source parent class as follows:
class View:
http_method_names = [ 'GET', 'POST', 'PUT ', ...]
DEF the init (Self, kwargs **):
for Key, kwargs.items value in ():
setattr (Self, Key, value)

@classonlymethod
def as_view(cls, **initkwargs):
    for key in initkwargs:
        ...
    def view(request, * args, **kwargs):
        """
        实例化一个对象,对象名称为self,self是cls的对象,谁调用了as_view,cls就是谁(当前调用as_view的是LoginView),所以,此时的self就是LoginView实例化对象.
        """
        self = cls(**initkwargs)
        if hassttr(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)
    view.view_class = cls
    view.view_initkwargs = initwargs
    
    update_wrapper(view, cls, updated=())
    update_wrapper(view, cls.dispatch, assigned=())
    return view

def dispatch(self, request, *args, **kwargs):
    if request.method.lower() in self.http_method_name:
        # 通过getattr找到的属性,已和对象绑定,访问时不需要再指明对象了
        # 即不需要再: self.handler, 直接handler()执行
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)            

The above can be seen as_view source is a class method, and the method defined in the view function, and the function returns as_view the view, at this time url establish a corresponding relationship with one function, and begin waiting for the user request.

(4) When the request sent by the user (such as a get request), corresponding to url started view function, and passing the request object, an execution result View class view function is to return self.dispatch (request, * args, ** kwargs ) of the execution result, self herein refers to an instance object LoginView Since LoginView not dispatch method, so to execute the dispatch parent class APIView the same, APIView class's dispatch functions also find self by reflection (this when self refers to an instance of the object LoginView) get their class methods (i.e. LoginView), the dispatch function handler (request, * args, ** kwargs) represents execution LoginView class get method, the execution result is the dispatch of execution result, that is, the execution result corresponding to the request url view function, the final result will be returned to the user.
(2) APIView
use:

views.py code:

from rest_framework.views import APIView # 引入APIView
class LoginView(APIView): # 继承APIView
def get(self, request):
pass
def post(self, request):
pass

urls.py code:

from django.urls import path, include, re_path
from classbasedView import views
urlspatterns = [
re_path('login/$', views.LoginView.as_view())]
源码解读:

(1) Start django project: Python manage.py the runserver 127.0.0.1:8000
(2) starts loading settings.py file
(3) models.py read the file
(4) load views.py file
(5) loaded urls.py file execution as_view (): views.LoginView.as_view ()
(. 6) Since there is no as_view LoginView, thus to execute as_view APIView the parent class, parent class APIView relevant source follows:
class APIView (View):
.. .
# api_settings object is an instance of class APISettings
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
...
Settings = api_setings
Schema = DefaultSchema ()

@classmethod
def as_view(cls, **initkwargs):     # cls指LoginView
    if isinstence(getattr(cls, 'queryset', None), models.query.Queryset):
        ...
    # 下面一句表示去执行APIView父类(即View类)中的as_view方法
    view = super(APIView, cls).as_view(**initkwargs)
    view.cls = cls
    view.initkwargs = initkwargs
    return csrf_exempt(view)

def dispatch(self, request, *args, **kwargs):
    ...
    request = self.initialize_request(request, *args, **kwargs)
    ...
    try:
        self.initial(request, *args, **kwargs)
        if request.method.lower() in self.http_method_name:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        response = self.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

View source reference to the above interpretation, we know as_view method View Returns view function, the view corresponding to url at this time have already been established, the user waits for requests.

(7) When the request sent by the user (such as a get request), corresponding to url started view function, and passing the request object, an execution result View class view function is to return self.dispatch (request, * args, ** kwargs ) of the execution result, self refers to an instance where the object LoginView, LoginView no dispatch method dispatch it to perform the method of the parent class APIView Similarly, APIview class's dispatch functions are found by self reflection (in this case refers to an object instance of self LoginView) get your class methods (i.e. LoginView) is, in the function dispatch handler (request, * args, ** kwargs) indicates the get method LoginView class, which is the execution result of the execution result dispatch , which is requested to perform the function of the results of the corresponding view url, final results will be returned to the user.
IV. supplementary knowledge

  1. On decorators
    if class is a decorative function, then when the class loading time, decorator function executes, the following code:

class Person(object):
@classmethod # 相当于 sleeping = classmethod(sleeping)
def sleeping(cls):
print('Tom is sleeping')

print(sleeping) 
# 加载类时执行,结果是:<classmethod object at 0x000001F2C29C8198>

Note: The class will perform direct printing and print output, and will be performed only when the function call as follows:

def func():
print('Hello World!')

Load does not execute print function func

It is only when we call func () will execute printing

  1. __dict__方法
    class Person(object):
    def init(self, name, age):
    self.name = name
    self.age = age

    def sing(self):
    print('I am singing!')

p1 = Person('alex', 18)
print(p1.__dict__) # {'name':'alex', 'age':18}
print(Person.__dict__)
'''
{'module': 'main',
'init': <function Person.__init__ at 0x0000021E1A46A8C8>,
'sing': <function Person.sing at 0x0000021E1A46A950>,
'dict': <attribute 'dict' of 'Person' objects>,
'weakref': <attribute 'weakref' of 'Person' objects>,
'doc': None}
'''
总结:

Object .__ dict__ all the members return to the dictionary object;
class .__ dict__ Returns all members of the class of the dictionary;
we can remove the .name member through an object, no such value dictionary manner using .name nature of the object is to perform class getitem Method .

  1. Two ways to extend the functionality of the program
    now has the following two requirements:

A demand: measure the time add the following function (add function without rewriting the premise)

def add(x, y):
return x + y

Solution: decorator

def outer(func):
def inner(*args, **kwargs):
import time
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print(end_time - start_time)
return inner

@outer
def add(x, y):
return x + y

Two requirements: extension class of functions (without rewriting the premise Father class)

class Father(object):
def show(self):
print('father show is excuted!')

father = Father()
father.show()

Solution: re-write a class that inherits Father class, override the show () method call with super ()

class Son(Father):
def show(self):
print('son show is excuted!')
super().show()

= Son Son ()
son.show ()
Summary:

Process-oriented manner to extend the functionality of the program:
the decorator
object-oriented way to extend the functionality of the program:
class inheritance
method overrides
super () method performs the parent class

  1. super () function
    description: super () function is a way to call the parent class (super class) for multiple inheritance super is used to solve the problem with the class name to call the parent class method without problems directly when using single inheritance. but if you use multiple inheritance, involves the search order (MRO), repeated calls (diamond inheritance) and other problems.

MRO is the way class resolution order table, in fact, is the inheritance order table when the parent class method.

grammar:

super(type[, object-or-type])
参数:

type - Class
object-or-type - based, generally self
Return Value: None

== == Note: a difference Python3.x and Python2.x are: Pyhton3 can directly use the super () instead of XXX super (Class, self) .xxx..

Python3.x Python2.x in the super () Usage Comparison:

Python3.x example:

class A:
pass
class B(A):
def add(self, x):
super().add(x)

Python2.x example:

class A (object): # Python2.x remember to inherit Object
Pass
class B (A):
DEF the Add (X):
Super (B, Self) .add (X)
Examples:

class FooParent(object):
def init(self):
self.parent = 'I am the parent!'
print('Parent')

def bar(self, message):
    print('%s from Parent!' % message)
    

class FooChild (FooParent):
DEF the init (Self):
'' '
to form super (B, self) as a reference,
Super (FooChild, Self) first find FooChild parent (i.e. FooParent),
then class B (i.e. super () first parameter) is converted to object FooChild FooParent object
'' '
Super (FooChild, Self) __ .__ the init ()
Print (' Child ')

def bar(self, message):
    super(FooChild, self).bar(message)
    print('Child bar function!')
    print(self.parent)
    

if name == 'main':
fooChild = FooChild()
fooChild.bar('HelloWorld')

Results of the:

Parent

Child

HelloWorld from Parent!

Child bar fuction!

Guess you like

Origin www.cnblogs.com/luodaoqi/p/11907525.html