Detailed explanation of Django request and response: in-depth understanding of the core mechanism of Web Http interaction

This article explores the request and response processing in Django in depth, from the basics and life cycle of Django request and response to the detailed introduction of HttpRequest and HttpResponse objects. Also, discusses Django's views and request and response handling, as well as security and asynchronous processing considerations. Finally, compare the similarities and differences between Django and Flask, FastAPI and other frameworks in request response processing. Whether you're new to Django or an experienced developer, this article can help you better understand Django's request and response handling.

1. Basic knowledge of Django request HttpRequest and response HttpResponse

In web applications, request and response patterns are very important concepts. When the user enters a URL in the browser address bar or clicks on a link, a request is sent to the server. After the server has processed the request, it will return a response to the browser. This is a typical HTTP request-response pattern.

1.1 Django's request object HttpRequest

In Django, when an HTTP request arrives at the Django application, it is first converted into an HttpRequest object by a URLconf file. This object contains all relevant information about this HTTP request.

def view(request):
    # request 是一个 HttpRequest 对象
    print(request.method)  # 输出请求方法,比如 "GET" 或 "POST"

1.2 Django's response object HttpResponse

Django views must return an HttpResponse object. This object represents the server's response to the client (usually a browser). This HttpResponse object will be converted into an HTTP response and sent to the client.

from django.http import HttpResponse

def view(request):
    # 创建一个 HttpResponse 对象
    response = HttpResponse("Hello, World!")
    return response  # 这个响应将会被发送给客户端

1.3 HTTP method Get/Post

An HTTP method is an "instruction" that a client can issue to a server. The most common methods include GET and POST.

  • GET: Usually used to get (or query) resource information.
  • POST: Usually used to update resource information.

In Django, you can methodaccess the request's methods through the HttpRequest object's property:

def view(request):
    print(request.method)  # 输出请求方法,比如 "GET" 或 "POST"

2. The lifecycle of a Django request

Once a Django application receives an HTTP request, it goes through a series of stages that together form the request's lifecycle. Here are the details of the process:

2.1 Request arrives

When a request arrives in a Django application, it is first received by the WSGI server. A Django project is run as a Python application by a WSGI server such as Gunicorn or uWSGI.

# 这是一个简单的WSGI应用的示例,当然,实际的Django WSGI应用更加复杂
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return [b"Hello World!"]

2.2 URL parsing

Next, the request will be sent to the URL parser, and the URL parser will match the URL according to the list of URL patterns defined in the URLConf module. URL patterns are defined using Python's regular expressions.

# urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
]

2.3 View processing

Once the URL parser finds a matching pattern, it calls the view function associated with that pattern, passing the view the HttpRequest object and any parameters extracted from the URL.

# views.py
from django.http import HttpResponse

def special_case_2003(request):
    return HttpResponse("Special case for 2003")

def year_archive(request, year):
    return HttpResponse(f"Articles for {
      
      year}")

2.4 Response return

After the view function processes the request, it creates an HttpResponse object and returns it. This response object will go through a series of processing by the middleware, and finally be converted into an HTTP response, and then sent to the client.

# 视图函数返回一个响应
def view(request):
    response = HttpResponse("Hello, World!")
    return response  # 这个响应将会被发送给客户端

3. Django HttpRequest details

In Django, all HTTP requests are encapsulated in the HttpRequest object. Below we will introduce the common properties and methods of the HttpRequest object in detail.

3.1 HttpRequest attributes

The HttpRequest object has many properties that help us obtain detailed information about the HTTP request. Here are some of the most commonly used properties:

  • path : A string representing the path of the request, not including the domain name or the path of the root URL of the site.

  • method : A string representing the method of the HTTP request. Common values ​​are "GET", "POST", etc.

  • GET : A dictionary-like object containing all GET parameters.

  • POST : A dictionary-like object containing all POST parameters.

  • COOKIES : A dictionary containing all cookies. Both keys and values ​​are strings.

  • FILES : A dictionary-like object containing all uploaded files.

  • user : A User object representing the current user. If the user is not currently logged in, this will be an AnonymousUser instance.

def view(request):
    # 打印一些 HttpRequest 属性的值
    print(request.path)  # 输出请求路径,比如 "/my-path/"
    print(request.method)  # 输出请求方法,比如 "GET"
    print(request.GET)  # 输出 GET 参数,比如 <QueryDict: {'key': ['value']}>
    print(request.user)  # 输出当前用户,如果用户未登录,将输出 AnonymousUser

3.2 HttpRequest method

In addition to properties, the HttpRequest object has some useful methods:

  • is_ajax() : Return True if the request was made via XMLHttpRequest.

  • is_secure() : Return True if the request was made over HTTPS.

  • is_authenticated() : Returns True if the current user is logged in.

def view(request):
    # 打印一些 HttpRequest 方法的返回值
    print(request.is_ajax())  # 如果请求是 AJAX 请求,输出 True
    print(request.is_secure())  # 如果请求是 HTTPS 请求,输出 True
    print(request.is_authenticated())  # 如果当前用户已登录,输出 True

4. Django view View and request HttpRequest processing

In Django, a view is a Python function that takes a web request and returns a web response. This response can be the HTML content of a Web page, a redirect, a 404 error, an XML document, an image, or any other type of content. Simply put, the job of a Django view is to accept a web request and return a web response.

4.1 Create a view

In Django, creating a view is just a matter of defining a Python function that takes a HttpRequestobject as its first argument and returns a HttpResponseobject. As follows:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello, World!")

In this example, hellothe function is a view that takes a HttpRequestobject and returns an HttpResponseobject containing "Hello, World!".

4.2 View parameters

The first argument to a view function is always HttpRequestthe object, and the arguments captured from the URL will be passed to the view function as additional arguments. For example:

from django.http import HttpResponse

def hello(request, name):
    return HttpResponse(f"Hello, {
      
      name}!")

In this example, hellothe view takes two parameters: a HttpRequestobject and a namestring. You can define in the URLConf how to extract this nameparameter from the URL.

4.3 HttpResponse object

Views must return a HttpResponseobject. HttpResponseThe class django.httpis defined in the module and represents an HTTP response, or a response from the server to the client.

HttpResponseObjects usually contain text content, either HTML or JSON. In addition to the text content, you can also control other HTTP response parameters by setting HttpResponsedifferent properties (such as content_typeand ).status

from django.http import HttpResponse

def hello(request):
    response = HttpResponse("Hello, World!", content_type="text/plain", status=200)
    return response

5. Django HttpResponse details

The HttpResponse object is the result object returned in the Django view, which is returned by the Django view and delivered to the client through the Django framework.

5.1 HttpResponse attribute

The HttpResponse object has some common properties that we can use to define our response. Here are some common properties:

  • content : The body content of the response, usually a string or byte string.

  • status_code : HTTP status code, such as 200, 404, etc.

  • content_type : The MIME type of the response, default is 'text/html'.

from django.http import HttpResponse

def view(request):
    response = HttpResponse()
    response.content = "Hello, World!"
    response.status_code = 200
    response.content_type = 'text/plain'
    return response

5.2 HttpResponse method

In addition to properties, the HttpResponse object has some useful methods:

  • set_cookie(key, value, max_age=None, expires=None) : Set a cookie. key is the name of the cookie, and value is the value of the cookie. max_age is the maximum lifetime of the cookie, in seconds. expires is the expiration time of the Cookie, which is a datetime object or UNIX timestamp.

  • delete_cookie(key) : delete a cookie.

from django.http import HttpResponse

def view(request):
    response = HttpResponse("Hello, World!")
    response.set_cookie('my_cookie', 'cookie_value', max_age=60*60*24)  # 设置一个一天后过期的 Cookie
    return response

5.3 Special HttpResponse objects

In addition to ordinary HttpResponse objects, Django also provides some special HttpResponse objects for generating specific responses. For example:

  • JsonResponse : This response object takes a dictionary or list and returns a response of type application/json.

  • HttpResponseRedirect : This response object is used to generate a redirection response.

  • HttpResponseNotFound : This response object is used to generate a 404 error response.

from django.http import JsonResponse, HttpResponseRedirect, HttpResponseNotFound

def view_json(request):
    return JsonResponse({
    
    'key': 'value'})  # 返回一个 JSON 响应

def view_redirect(request):
    return HttpResponseRedirect('/another-url/')  # 重定向到另一个 URL

def view_404(request):
    return HttpResponseNotFound('<h1>Page not found</h1>')  # 返回一个 404 错误

6. Django view View and HttpResponse response processing

In Django, views are the main handlers of web requests, and are also responsible for building and returning responses. Views receive HttpRequest objects as parameters and generate HttpResponse objects as return values. Now that we've discussed HttpRequest and HttpResponse in detail, let's look at how to handle them in the view.

6.1 Processing requests

Processing the request is mainly to extract the data of the HttpRequest object, and then execute the corresponding logic based on these data.

def view(request):
    # 获取 GET 请求的参数
    name = request.GET.get('name', 'Guest')
    # 根据请求参数执行逻辑
    message = f"Hello, {
      
      name}!"
    return HttpResponse(message)

In this example, we get the 'name' parameter from the GET request and use it to generate a welcome message.

6.2 Building the response

Building a response basically involves creating an HttpResponse object and then populating it with content.

def view(request):
    # 创建 HttpResponse 对象
    response = HttpResponse()
    # 填充响应内容
    response.content = "Hello, World!"
    response.status_code = 200
    response['Content-Type'] = 'text/plain'
    return response

In this example, we create an HttpResponse object, then set its content, status code, and Content-Type header.

6.3 Shortcuts

In Django views, we often need to do some common operations, such as rendering a template, redirecting to another URL, or returning a 404 error. To simplify these operations, Django provides some shortcuts.

from django.shortcuts import render, redirect, get_object_or_404
from .models import MyModel

def view(request):
    # 渲染一个模板
    context = {
    
    'key': 'value'}
    return render(request, 'my_template.html', context)

def redirect_view(request):
    # 重定向到另一个 URL
    return redirect('/another-url/')

def detail_view(request, pk):
    # 获取一个对象或返回 404 错误
    obj = get_object_or_404(MyModel, pk=pk)
    return render(request, 'detail.html', {
    
    'obj': obj})

7. Security considerations for Django requests and responses

Security is a very important consideration when processing web requests and generating responses. Fortunately, Django provides some built-in tools and techniques to help us increase the security of our applications.

7.1 CSRF Protection

Cross-site request forgery (CSRF) is an attack in which an attacker forges a user's request. Django provides a CSRF protection mechanism that automatically checks for CSRF tokens when processing POST requests.

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt  # 用这个装饰器来禁用 CSRF 保护
def my_view(request):
    # view code here...

In most cases, you should let Django handle CSRF protection automatically. But in some cases, you may need to disable it, like the example above.

7.2 Secure data storage

When you receive sensitive information, such as passwords, while processing a request, you should use the secure methods provided by Django to store this information.

from django.contrib.auth.hashers import make_password

def register(request):
    password = request.POST['password']
    hashed_password = make_password(password)  # 使用哈希函数来安全存储密码
    # save hashed_password to database...

7.3 Security Settings for HTTP Response Headers

Django provides settings that you can use to increase the security of HTTP response headers, such as SECURE_CONTENT_TYPE_NOSNIFFand SECURE_BROWSER_XSS_FILTER. You can configure them in your Django settings.

# settings.py
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True

7.4 Secure handling of user input

Never trust user-entered data. You should always sanitize and validate user input data.

from django.core.exceptions import ValidationError

def view(request):
    comment = request.POST['comment']
    if len(comment) > 100:
        raise ValidationError("Comment is too long!")
    # save comment to database...

8. Django asynchronous request and response

Django 3.1 introduced asynchronous view and middleware support, which means you can use Python's asyncand awaitkeywords to handle asynchronous tasks. This is useful for handling I/O bound tasks or other tasks that can benefit from concurrent execution.

8.1 Asynchronous Views

The way to create an asynchronous view is very similar to creating a synchronous view, but you need to define the view function as a async deffunction, and then use the keyword in the function body await.

from django.http import JsonResponse

async def async_view(request):
    data = await get_data()  # 假设 get_data 是一个异步函数
    return JsonResponse(data)

In this example, get_dataan asynchronous function, we use awaitthe keyword to call it. While Django waits get_datafor completion, it can free up server resources to handle other requests.

8.2 Asynchronous middleware

You can also create asynchronous middleware, which can handle requests and responses before entering the view or after leaving the view.

class SimpleMiddleware:
    async def __call__(self, request, get_response):
        response = await get_response(request)
        return response

In this case, SimpleMiddlewarean asynchronous middleware that does nothing before and after processing the request but simply passes the request on to the next middleware or view.

8.3 Database Operation

In Django's asynchronous views or middleware, you should not perform synchronous database operations, because this may block the event loop. You should use the functions provided by Django asgiref.sync.sync_to_asyncto wrap synchronous database operations in a thread.

from asgiref.sync import sync_to_async
from django.contrib.auth.models import User

async def async_view(request):
    get_user = sync_to_async(User.objects.get)
    user = await get_user(id=1)
    return JsonResponse({
    
    'username': user.username})

In this example, we use sync_to_asyncthe function to User.objects.getwrap the into a thread, and then use awaitthe keyword to call it in the asynchronous view.

Of course, next we will compare the similarities and differences between Django and other mainstream Python frameworks (such as Flask and FastAPI) in request and response processing.

Summary. Comparison of Django and other mainstream Python frameworks in the request-response section

9.1 Django vs Flask

Flask is another popular Python web framework. Compared to Django, Flask is a more lightweight framework with more customization.

  • Request object: Flask's object is similar requestto Django's object in many ways, but Flask's object is syntactically more concise. In Flask, you can access POST parameters directly via , while in Django, you need to use .HttpRequestrequestrequest.form['key']request.POST.get('key')

  • Response objects: Flask allows you to return strings directly from the view, and then automatically converts them to Responseobjects, while Django requires you to explicitly create a HttpResponseobject.

  • URL parameters: Flask provides a concise way to define parameters in the URL, eg @app.route('/user/<username>'), in Django, you need to use regular expressions in urls.py to define URL parameters.

# Flask
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

# Django
from django.urls import path

def show_user_profile(request, username):
    # show the user profile for that user
    return HttpResponse('User %s' % username)

urlpatterns = [
    path('user/<str:username>/', show_user_profile),
]

9.2 Django vs FastAPI

FastAPI is an emerging Python web framework, which features fast, simple and high performance, and has built-in support for asynchronous programming.

  • Type checking: FastAPI supports Python type checking. You can directly define the type in the parameter, and FastAPI will automatically perform data verification. Whereas in Django, you need to validate data and handle errors yourself.

  • Asynchronous programming: Although Django 3.1 began to support asynchronous views and middleware, FastAPI's support for asynchronous programming is more complete. asyncYou can use the and keywords in FastAPI awaitto define asynchronous path operation functions, while in Django, you may need to use asgiref.sync.sync_to_asyncto wrap database operations.

  • Automatic documentation: FastAPI can automatically generate API documentation based on your code, which can help you better test and debug your API. In Django, you need to use a third-party library such as DRF or manually write API documentation.

# FastAPI
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {
    
    "item_id": item_id}

In general, Django, Flask, and FastAPI are all excellent Python web frameworks, and they each have their own advantages. Which one to choose depends on your project requirements, and which programming paradigm you prefer to use.

If it is helpful, please pay more attention to
the personal WeChat public account: [Python full perspective]
TeahLead_KrisChang, 10+ years of experience in the Internet and artificial intelligence industry, 10+ years of experience in technology and business team management, Tongji Software Engineering Bachelor, Fudan Engineering Management Master, Aliyun certified cloud service senior architect, head of AI product business with hundreds of millions of revenue.

Guess you like

Origin blog.csdn.net/magicyangjay111/article/details/131624340