This article is participating in Python Theme Month. See the link for details

Rest cannot be enjoyed by lazy people.~

preface

In the article on Djangos Routing layer, I explained how to match routes with view functions. In this article, I will introduce Django’s view functions, known as Djangos view layer.

View layer functionality

Routed in the routing layer and view function matching, routing after the success of the match will execute the corresponding view function, view function is used to deal with corresponding to the url request and returns the response data, in the process of the request – response generally involves two points, the first is the view layer will interact and layer model (data), to add and delete data, The second is that the view layer needs to pass some data to the front-end HTML page.

The request object

In the Django request lifecycle, a request sent by the client browser through the gateway is parsed into HTTP data encapsulated in a Request object. Each function in a view function must take a request parameter (the name can be arbitrary, To receive the Request object, what do I get if I print the Request object in a view function?

def index(request) :
    print(request)   # 
    return HttpResponse('js_str')
Copy the code

There are many methods in the Request object to obtain the specific data requested by the client browser, such as the request method, the data carried by the request, and so on. Combine the front-end form form to see the method of the Request object, mainly divided into request.GET and request.POST two aspects, respectively represent the client browser GET request and POST request.

request.GET

The default request for the form is GET. When the request is GET, the data submitted by the front end and the back end will be directly followed by the URL as? As a delimiter between parameters and THE URL, different parameters are connected by am&. The parameters carried after the question mark have no effect on the routing, but only send the data in the form of get requests to the backend.

Note: GET requests are generally used to request pages, and the parameters carried after the question mark are usually used for things like filtering data on the back end, not for submitting data on the front end and back end. Any request sent by a page opened for the first time is a GET request.

<! -- Front-end HTML page: mu.html-->
<body>
    <form method="get">User name:<input type="text" name="username" placeholder="Please enter user name" id="username">Password:<input type="text" name="pwd" placeholder="Please enter your password" id="pwd">
        <input type="submit" value="Login">
    </form>
</body>
Copy the code
# views.py
def login(request) :
    print(F 'request mode{request.method}')
	print(request.get_full_path())   Get the full URL and the parameters after the question mark
	print(request.path)   # get url
    print(F 'get The data carried by the request{request.GET}')  # get a dictionary-like object with the same value as a dictionary
    print('Get the data carried by the request')
    print(request.GET.get('username'))
    print(request.GET.get('pwd'))
    return render(request, 'mu.html')
Copy the code

When you access 127.0.0.1:8000/login, the mu.html page is displayed. Enter the user name and password then click the login button, it becomes http://127.0.0.1:8000/login/? in the browser’s address bar Username =root&pwd=123, the corresponding view function at the back end will output the corresponding result as follows:

Request mode GET /first/login/? username=root&pwd=123/first/login/ get Request carries data <QueryDict: {'username': ['root'].'pwd': ['123']}> get the data carried by the request root123
Copy the code

request.POST

Post requests are used to submit data to the backend. When a post request is sent to the backend, the submitted data will not be displayed after the URL. The front end page for the POST request uses the front end registration page in the HTML article.

# views.py
def register(request) :
    if request.method == 'POST':

        print(F 'request mode{request.method}')
		
        # request.POST to retrieve user-submitted data, excluding files, and values in each key-value pair are lists
        res = request.POST
        # res.get('username') to get only the last element in the list
        print(res.get('username'), type(res.get('username')))

        # res.getList ('hobby') fetchthe list directly
        print(res.getlist('hobby'), type(res.getlist('hobby')))

        Get file data
        print(request.FILES)
        avatar_obj = request.FILES.get('avatar')   Get the file object
        print(avatar_obj.name)   Get the file name
        Save the file to a static file on the server
        with open(avatar_obj.name, 'wb') as f:
            for line in avatar_obj.chunks():  Save file data using chunks()
                f.write(line)
        return HttpResponse('Registration successful')
    return render(request, 'render_html.html')
Copy the code

Render_html.html is displayed when accessing 127.0.0.1:8000/register, enter username and password, and click Submit. The data input from the front end will be passed to the back end, and the back end view function will execute as follows:

Request mode POST root <class 'str'>
['read', 'outdoors'] <class 'list'>
<MultiValueDict: {'avatar': [<InMemoryUploadedFile: 5076e4181de45b78727ffca4e1f8e0a.png (image/png)>]}>
5076e4181de45b78727ffca4e1f8e0a.png
Copy the code

Request object other methods

In addition to the above request object methods, there are some other commonly used request object methods:

# Binary data sent from native browsers
print(request.body)

# get url
print(request.path)

Get the full URL and the parameters after the question mark
print(request.get_full_path())
Copy the code

HttpResponse & render & redirect

There are three basic ways to return data to the front page in view functions:

from django.shortcuts import render, redirect, HttpResponse

# HttpResponse returns the string to the front-end
return HttpResponse('hello world')

# render, which renders the template file into an HTML file and returns it to the browser, also supports transferring data to the template file
return render(request, 'index.html'.locals())

# redirect
return redirect('/index/')
Copy the code

All three internally return an HttpResponse object, so the view function must return an HttpResponse object.

JsonResponse

It’s a cliche that JSON-formatted data is often used for data interaction between different programming languages, and front-end data interaction can also be transmitted using JSON-formatted data. Serialization can be done using json modules:

import json
from django.shortcuts import HttpResponse

def my_json(request) :
    user_dict = {'name':'python'.'password':'123'}
    js_str = json.dumps(user_dict,ensure_ascii=False)
    return HttpResponse(js_str)
Copy the code

The Django framework provides a more convenient way to pass jSON-formatted data to JsonResponse. JsonResponse is also a class that inherits HttpResponse as follows:

from django.http import JsonResponse

def ab_json(request) :
    user_dic = {'name':'small farmhouse'.'password':'123'}

    # JsonResponse - If enSURE_ASCII is true in the json_dumps_params parameter, the serialized string returned in Chinese will not display properly
    return JsonResponse(user_dic, json_dumps_params={'ensure_ascii':False})
Copy the code

Note that JsonResponse can only serialize dictionaries by default. If you want to serialize data from other formats, you need to set the safe parameter to False. Otherwise, an exception will be thrown. The source code is as follows:

# JsonResponse section source code
class JsonResponse(HttpResponse) :

    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs) :
        if safe and not isinstance(data, dict) :raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type'.'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)
Copy the code

Therefore, we need to specify the safe parameter when serializing non-dictionary data types:

from django.http import JsonResponse

def test(request) :
    l = ['a'.'at']
    return JsonResponse(l, safe=False, json_dumps_params={'ensure_ascii': False})
Copy the code

FBV and CBV

The code of the logical processing part in the view layer can be functions or classes. The logic processing of the view layer before this is function processing request, namely FBV(Function Base Views). The following will introduce how CBV corresponds to URL and processes logic.

CBV(Class Base Views), which uses classes to handle requests in a view. Python is an object-oriented programming language, and many of the benefits of object-oriented programming (encapsulation, inheritance, polymorphism) would be missed if only functions were developed. So Django later added class-based View. Let’s write a View in a class. There are two main advantages to doing this:

① Improved code reuse, can use object-oriented technology, such as Mixin (multiple inheritance)

② Different functions can be used for different HTTP methods, rather than through a lot of if judgment, improve code readability

CBV can be directly matched to the corresponding method execution according to the different request mode. The following is the code using CBV view layer and routing layer:

# views.py
from django.views import View

class CBV(View) :
    def get(self, request) :
        return HttpResponse('get')
    
    def post(self, request) :
        return HttpResponse('post')
    
# urls.py
from django.conf.urls import url
from first import views

urlpatterns = [
    url(r'cbv/', views.CBV.as_view())
]
Copy the code

When accessing 127.0.0.1:8000/ CBV, the corresponding CBV method is automatically executed depending on the request. So how does Django implement this effect? When a request arrives at djangos back end, it first passes through the routing layer, urls.py, and then executes the corresponding view function after the route matches. If you can’t find it in the parent class, you have to do it in that order.

This method returns the closure function view, so the relationship between url and view function is changed to URL (r’ CBV /’, views.view), which is the same form as FBV.

Then look at the closure function View, instantiate the CBV class defined by the view layer in this function, and call the dispatch method of the object. Since there is no such method in the custom CBV class, according to the object’s attribute search order, we need to find the Dispatch method in the parent class View. In other words, if the DISPATCH method is defined in the CBV, it overrides the View class.

Finally, the reflection method is adopted in the Dispatch method, which dynamically matches to the corresponding method in the view class according to the different request mode.

conclusion

This article was first published on the wechat public account ** “Cheng Xuyuan Xiaozhuang” **, and also on the nuggets.

The code word is not easy, reprint please explain the source, pass by the little friends of the lovely little finger point like and then go (╹▽╹)