关于python:详解Django请求与响应深入理解Web-Http交互的核心机制

36次阅读

共计 10031 个字符,预计需要花费 26 分钟才能阅读完成。

本文深入探讨了 Django 中的申请与响应解决,从 Django 申请和响应的基础知识、生命周期,到 HttpRequest 和 HttpResponse 对象的具体介绍。同时,探讨了 Django 的视图和申请、响应解决,以及安全性和异步解决的思考。最初,比照了 Django 与 Flask、FastAPI 等框架在申请响应解决上的异同。无论您是 Django 老手还是有教训的开发者,这篇文章都能帮忙您更好地了解 Django 的申请和响应解决。

1. Django 申请 HttpRequest 和响应 HttpResponse 的基础知识

在 Web 应用程序中,申请和响应模式是十分重要的概念。当用户在浏览器地址栏输出一个 URL 或者点击某个链接时,会向服务器发送一个申请。服务器解决完这个申请后,会返回一个响应给浏览器。这就是典型的 HTTP 申请 - 响应模式。

1.1 Django 的申请对象 HttpRequest

在 Django 中,当一个 HTTP 申请达到 Django 利用时,它首先会被某个 URLconf 文件转化为一个 HttpRequest 对象。这个对象蕴含了这次 HTTP 申请的所有相干的信息。

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

1.2 Django 的响应对象 HttpResponse

Django 的视图必须返回一个 HttpResponse 对象。这个对象示意服务器给客户端(通常是浏览器)的响应。这个 HttpResponse 对象会被转化为一个 HTTP 响应,而后被发送到客户端。

from django.http import HttpResponse

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

1.3 HTTP 办法 Get/Post

HTTP 办法是客户端能够对服务器收回的一种 “ 指令 ”。最常见的办法包含 GET 和 POST。

  • GET: 通常用于获取(或查问)资源信息。
  • POST: 通常用于更新资源信息。

在 Django 中,你能够通过 HttpRequest 对象的 method 属性来拜访这个申请的办法:

def view(request):
    print(request.method)  # 输入申请办法,比方 "GET" 或 "POST"

2. Django 申请的生命周期

一旦 Django 利用收到了一个 HTTP 申请,它会经验一系列的阶段,这些阶段独特形成了申请的生命周期。以下是这个过程的详述:

2.1 申请达到

当一个申请达到 Django 利用时,它首先会被 WSGI 服务器接管。Django 我的项目被 WSGI 服务器(如 Gunicorn 或 uWSGI)作为一个 Python 利用程序运行。

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

2.2 URL 解析

接下来,申请会被送到 URL 解析器,URL 解析器会依据 URLConf 模块中定义的 URL 模式列表对 URL 进行匹配。URL 模式是应用 Python 的正则表达式来定义的。

# 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 视图解决

一旦 URL 解析器找到了匹配的模式,它会调用与该模式关联的视图函数,并将 HttpRequest 对象和从 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 响应返回

视图函数解决完申请后,会创立一个 HttpResponse 对象并返回。这个响应对象会通过中间件的一系列解决,最终会被转换为一个 HTTP 响应,而后发送给客户端。

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

3. Django HttpRequest 详述

在 Django 中,所有的 HTTP 申请都被封装在 HttpRequest 对象中。上面咱们将具体介绍 HttpRequest 对象的常见属性和办法。

3.1 HttpRequest 属性

HttpRequest 对象有很多属性,能够帮忙咱们获取 HTTP 申请的详细信息。以下是一些最罕用的属性:

  • path: 一个字符串,示意申请的门路,不包含域名或者站点根 URL 的门路。
  • method: 一个字符串,示意 HTTP 申请的办法。常见的值有 “GET”,”POST” 等。
  • GET: 一个相似字典的对象,蕴含所有的 GET 参数。
  • POST: 一个相似字典的对象,蕴含所有的 POST 参数。
  • COOKIES: 一个字典,蕴含所有的 cookie。键和值都为字符串。
  • FILES: 一个相似字典的对象,蕴含所有的上传文件。
  • user: 一个示意以后用户的 User 对象。如果用户以后未登录,这将是一个 AnonymousUser 实例。
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 办法

除了属性,HttpRequest 对象还有一些有用的办法:

  • is_ajax(): 如果申请是通过 XMLHttpRequest 收回的,返回 True。
  • is_secure(): 如果申请是通过 HTTPS 收回的,返回 True。
  • is_authenticated(): 如果以后用户曾经登录,返回 True。
def view(request):
    # 打印一些 HttpRequest 办法的返回值
    print(request.is_ajax())  # 如果申请是 AJAX 申请,输入 True
    print(request.is_secure())  # 如果申请是 HTTPS 申请,输入 True
    print(request.is_authenticated())  # 如果以后用户已登录,输入 True

4. Django 视图 View 和申请 HttpRequest 解决

在 Django 中,视图是一个 Python 函数,用于接管一个 Web 申请并返回一个 Web 响应。这个响应能够是 Web 页面的 HTML 内容,重定向,404 谬误,XML 文档,图像,或者任何其余类型的内容。简略来说,Django 视图的工作就是承受一个 Web 申请并返回一个 Web 响应。

4.1 创立视图

在 Django 中,创立一个视图只须要定义一个 Python 函数,这个函数须要承受一个 HttpRequest 对象作为第一个参数,而后返回一个 HttpResponse 对象。如下所示:

from django.http import HttpResponse

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

在这个例子中,hello 函数就是一个视图,它接管一个 HttpRequest 对象,而后返回一个蕴含 “Hello, World!” 的 HttpResponse 对象。

4.2 视图参数

视图函数的第一个参数总是 HttpRequest 对象,而从 URL 中捕捉的参数将作为额定的参数传递给视图函数。例如:

from django.http import HttpResponse

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

在这个例子中,hello 视图承受两个参数:一个 HttpRequest 对象和一个 name 字符串。你能够在 URLConf 中定义如何从 URL 中提取这个 name 参数。

4.3 HttpResponse 对象

视图必须返回一个 HttpResponse 对象。HttpResponse 类在 django.http 模块中定义,示意一个 HTTP 响应,或者说是一个服务器给客户端的回应。

HttpResponse 对象通常蕴含文本内容,能够是 HTML,也能够是 JSON。除了文本内容,你还能够通过设置 HttpResponse 的不同属性(比方 content_typestatus)来管制其余 HTTP 响应的参数。

from django.http import HttpResponse

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

5. Django HttpResponse 详述

HttpResponse 对象是 Django 视图中返回的后果对象,它是由 Django 视图返回并通过 Django 框架传送给客户端的。

5.1 HttpResponse 属性

HttpResponse 对象有一些罕用的属性,咱们能够应用它们来定义咱们的响应。以下是一些常见的属性:

  • content: 响应的主体内容,通常为一个字符串或字节串。
  • status_code: HTTP 状态码,如 200、404 等。
  • content_type: 响应的 MIME 类型,默认为 ‘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 办法

除了属性,HttpResponse 对象还有一些有用的办法:

  • set_cookie(key, value, max_age=None, expires=None): 设置一个 Cookie。key 是 Cookie 的名字,value 是 Cookie 的值。max_age 是 Cookie 的最大生存工夫,单位是秒。expires 是 Cookie 的过期工夫,是一个 datetime 对象或 UNIX 工夫戳。
  • delete_cookie(key): 删除一个 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 非凡的 HttpResponse 对象

除了一般的 HttpResponse 对象,Django 还提供了一些非凡的 HttpResponse 对象,用于生成特定的响应。例如:

  • JsonResponse: 这个响应对象接管一个字典或列表,并返回一个 application/json 类型的响应。
  • HttpResponseRedirect: 这个响应对象用于生成一个重定向响应。
  • HttpResponseNotFound: 这个响应对象用于生成一个 404 谬误响应。
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 和 HttpResponse 响应解决

在 Django 中,视图是 Web 申请的次要解决者,同时也负责构建和返回响应。视图接管 HttpRequest 对象作为参数,生成 HttpResponse 对象作为返回值。咱们曾经具体探讨了 HttpRequest 和 HttpResponse,当初咱们来看看如何在视图中解决它们。

6.1 解决申请

解决申请次要是提取 HttpRequest 对象的数据,而后依据这些数据执行相应的逻辑。

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

在这个例子中,咱们从 GET 申请中获取 ‘name’ 参数,而后用它来生成一条欢送音讯。

6.2 构建响应

构建响应次要是创立 HttpResponse 对象,而后填充其内容。

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

在这个例子中,咱们创立了一个 HttpResponse 对象,而后设置了其内容、状态码和 Content-Type 头。

6.3 快捷方式

在 Django 视图中,咱们常常须要做一些常见的操作,比方渲染一个模板,重定向到另一个 URL,或者返回一个 404 谬误。为了简化这些操作,Django 提供了一些快捷方式。

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. Django 申请和响应的安全性思考

在解决 Web 申请和生成响应时,安全性是一个十分重要的思考因素。侥幸的是,Django 提供了一些内置的工具和技术来帮忙咱们减少应用程序的安全性。

7.1 CSRF 爱护

跨站申请伪造(CSRF)是一种攻击方式,攻击者能够伪造用户的申请。Django 提供了 CSRF 爱护机制,能够在解决 POST 申请时主动查看 CSRF 令牌。

from django.views.decorators.csrf import csrf_exempt

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

在大多数状况下,你应该让 Django 主动解决 CSRF 爱护。然而在某些状况下,你可能须要禁用它,比方下面的例子。

7.2 平安的数据存储

当你在解决申请时接管到敏感信息,如明码,你应该应用 Django 提供的平安办法来存储这些信息。

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 HTTP 响应头的平安设置

Django 提供了一些设置,你能够应用它们来减少 HTTP 响应头的安全性,如 SECURE_CONTENT_TYPE_NOSNIFFSECURE_BROWSER_XSS_FILTER。你能够在你的 Django 设置中配置它们。

# settings.py
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True

7.4 用户输出的平安解决

永远不要信赖用户输出的数据。你应该始终对用户输出的数据进行荡涤和验证。

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 异步申请和响应

Django 3.1 引入了异步视图和中间件反对,这意味着你能够应用 Python 的 asyncawait 关键字来解决异步工作。这对于解决 I/O 绑定工作或其余能够从并发执行中受害的工作十分有用。

8.1 异步视图

创立异步视图的形式与创立同步视图十分类似,然而你须要将视图函数定义为 async def 函数,而后在函数体中应用 await 关键字。

from django.http import JsonResponse

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

在这个例子中,get_data 是一个异步函数,咱们应用 await 关键字来调用它。当 Django 期待 get_data 实现时,它能够开释服务器资源来解决其余申请。

8.2 异步中间件

你也能够创立异步中间件,它能够解决进入视图之前或来到视图之后的申请和响应。

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

在这个例子中,SimpleMiddleware 是一个异步中间件,它在解决申请之前和之后没有做任何事件,只是简略地将申请传递给下一个中间件或视图。

8.3 数据库操作

在 Django 的异步视图或中间件中,你不应该执行同步的数据库操作,因为这可能会阻塞事件循环。你应该应用 Django 提供的 asgiref.sync.sync_to_async 函数将同步的数据库操作包装到一个线程中。

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})

在这个例子中,咱们应用 sync_to_async 函数将 User.objects.get 包装到一个线程中,而后在异步视图中应用 await 关键字来调用它。

当然,接下来咱们就来比拟一下 Django 与其余支流 Python 框架(如 Flask 和 FastAPI)在申请和响应解决上的异同。

总结. Django 与其余支流 Python 框架在申请响应局部的比拟

9.1 Django vs Flask

Flask 是另一个风行的 Python web 框架,相比 Django,Flask 是一个更为轻量级的框架,具备更高的定制性。

  • 申请对象: Flask 的 request 对象和 Django 的 HttpRequest 对象在许多方面是类似的,但 Flask 的 request 对象在语法上更为简洁。在 Flask 中,你能够间接通过 request.form['key'] 来拜访 POST 参数,而在 Django 中,你须要应用 request.POST.get('key')
  • 响应对象: Flask 容许你间接从视图返回字符串,而后主动将其转化为 Response 对象,而 Django 则须要你显式地创立一个 HttpResponse 对象。
  • URL 参数: Flask 提供了一种简洁的形式来在 URL 中定义参数,如 @app.route('/user/<username>'),而在 Django 中,你须要在 urls.py 中应用正则表达式来定义 URL 参数。
# 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 是一个新兴的 Python web 框架,它的特色是疾速、简略和高性能,而且内建对异步编程的反对。

  • 类型查看: FastAPI 反对 Python 的类型查看,你能够在参数中间接定义类型,FastAPI 会主动进行数据验证。而在 Django 中,你须要本人验证数据并处理错误。
  • 异步编程: 尽管 Django 3.1 开始反对异步视图和中间件,然而 FastAPI 在异步编程方面的反对更为欠缺。你能够在 FastAPI 中应用 asyncawait 关键字来定义异步的门路操作函数,而在 Django 中,你可能须要应用 asgiref.sync.sync_to_async 来包装数据库操作。
  • 主动文档: FastAPI 能够依据你的代码主动生成 API 文档,这能够帮忙你更好地测试和调试你的 API。而在 Django 中,你须要应用如 DRF 的第三方库或手动编写 API 文档。
# FastAPI
from fastapi import FastAPI

app = FastAPI()

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

总的来说,Django、Flask 和 FastAPI 都是优良的 Python web 框架,它们各有各的长处。抉择哪一个取决于你的我的项目需要,以及你更偏向于应用哪种编程范式。

如有帮忙,请多关注
集体微信公众号:【Python 全视角】
TeahLead_KrisChang,10+ 年的互联网和人工智能从业教训,10 年 + 技术和业务团队治理教训,同济软件工程本科,复旦工程治理硕士,阿里云认证云服务资深架构师,上亿营收 AI 产品业务负责人。

正文完
 0