MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python Django框架中的视图与模板机制

2021-08-143.3k 阅读

Django 视图基础

在 Django 框架中,视图起着至关重要的作用。简单来说,视图就是一个 Python 函数,它接收一个 Web 请求并返回一个 Web 响应。响应可以是网页的 HTML 内容、重定向、404 错误、XML 文档,或者其他任何类型的内容。

定义简单视图

以下是一个最简单的视图示例:

from django.http import HttpResponse

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

在上述代码中,我们从 django.http 模块导入了 HttpResponse 类,这个类用于创建 HTTP 响应对象。hello_world 函数就是一个视图函数,它接收一个 request 参数,这个参数包含了客户端发送的所有请求信息。函数返回一个 HttpResponse 对象,其内容为 "Hello, World!"。

视图与 URL 映射

仅仅定义视图函数还不够,我们需要将视图函数与 URL 进行映射,这样当用户访问特定 URL 时,Django 才能找到对应的视图函数来处理请求。在项目的 urls.py 文件中进行如下配置:

from django.contrib import admin
from django.urls import path
from.views import hello_world

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', hello_world),
]

在上述 urls.py 配置中,我们使用 path 函数将 hello/ 这个 URL 路径映射到了 hello_world 视图函数。当用户在浏览器中访问 http://example.com/hello/ 时,Django 就会调用 hello_world 函数并返回相应的响应。

视图的请求处理

请求对象

视图函数的第一个参数 requestHttpRequest 类的实例,它包含了客户端请求的所有信息,如请求方法(GET、POST 等)、请求头、请求体等。

from django.http import HttpResponse

def method_demo(request):
    if request.method == 'GET':
        return HttpResponse("This is a GET request.")
    elif request.method == 'POST':
        return HttpResponse("This is a POST request.")
    else:
        return HttpResponse("Unsupported request method.")

在上述代码中,通过检查 request.method,我们可以针对不同的请求方法返回不同的响应。

获取请求参数

  1. GET 参数:如果是 GET 请求,我们可以通过 request.GET 获取 URL 中的查询参数。
from django.http import HttpResponse

def get_params(request):
    name = request.GET.get('name', 'default_name')
    return HttpResponse(f"Your name is {name}")

在上述代码中,request.GET.get('name', 'default_name') 尝试从 GET 请求的参数中获取名为 name 的值,如果不存在则返回 default_name

  1. POST 参数:对于 POST 请求,我们通过 request.POST 获取表单数据。假设我们有一个包含用户名和密码的表单:
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <form method="post" action="/login/">
        {% csrf_token %}
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required><br><br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required><br><br>
        <input type="submit" value="Login">
    </form>
</body>
</html>

对应的视图函数可以这样处理:

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect

@csrf_protect
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 进行登录验证逻辑
        if username and password:
            return HttpResponse(f"Welcome, {username}!")
        else:
            return HttpResponse("Invalid credentials.")
    else:
        return HttpResponse("Please submit the form.")

在上述代码中,@csrf_protect 装饰器用于防止跨站请求伪造攻击。request.POST.get('username')request.POST.get('password') 分别获取表单中名为 usernamepassword 的值。

视图的响应处理

HttpResponse 类

HttpResponse 类是 Django 中最基本的响应类,我们前面已经多次使用。除了直接返回字符串内容,我们还可以设置响应头、状态码等。

from django.http import HttpResponse

def custom_response(request):
    response = HttpResponse("Custom response content")
    response['Content-Type'] = 'text/plain'
    response.status_code = 201
    return response

在上述代码中,我们创建了一个 HttpResponse 对象,设置了 Content-Type 响应头为 text/plain,并将状态码设置为 201

重定向响应

有时我们需要将用户重定向到另一个 URL。Django 提供了 HttpResponseRedirect 类来实现这一点。

from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_view(request):
    return HttpResponseRedirect(reverse('home'))

在上述代码中,reverse 函数根据 URL 模式的名称 home 生成对应的 URL,然后 HttpResponseRedirect 将用户重定向到该 URL。

JSON 响应

在现代 Web 开发中,JSON 格式的数据传输非常常见。Django 提供了 JsonResponse 类来方便地返回 JSON 数据。

from django.http import JsonResponse

def json_view(request):
    data = {'message': 'This is a JSON response', 'code': 200}
    return JsonResponse(data)

上述代码返回一个包含 messagecode 字段的 JSON 响应。JsonResponse 会自动设置 Content-Typeapplication/json

Django 模板机制基础

Django 的模板机制允许我们将业务逻辑和显示逻辑分离。模板是包含特殊语法的文本文件,用于生成最终的输出,通常是 HTML。

创建模板

首先,在项目的 templates 目录下创建一个模板文件,例如 index.html

<!DOCTYPE html>
<html>
<head>
    <title>My Django Page</title>
</head>
<body>
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
</body>
</html>

在上述模板中,{{ title }}{{ content }} 是模板变量,它们的值将在视图中传递过来。

加载和渲染模板

在视图中,我们使用 render 函数来加载和渲染模板。

from django.shortcuts import render

def template_view(request):
    context = {
        'title': 'Welcome to My Site',
        'content': 'This is the main content of the page.'
    }
    return render(request, 'index.html', context)

在上述代码中,render 函数的第一个参数是 request 对象,第二个参数是模板文件名 index.html,第三个参数 context 是一个字典,包含了要传递给模板的变量。

模板变量

基本变量使用

模板变量是模板中最重要的部分之一。我们可以在模板中使用点号(.)来访问对象的属性或方法。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_info(self):
        return f"{self.name} is {self.age} years old."

def person_view(request):
    person = Person('John', 30)
    context = {
        'person': person
    }
    return render(request, 'person.html', context)

person.html 模板中:

<!DOCTYPE html>
<html>
<head>
    <title>Person Info</title>
</head>
<body>
    <p>Name: {{ person.name }}</p>
    <p>Age: {{ person.age }}</p>
    <p>Info: {{ person.get_info }}</p>
</body>
</html>

在上述代码中,通过 person.nameperson.ageperson.get_info 分别访问 Person 对象的属性和方法。

过滤器

过滤器用于在模板变量显示之前对其进行修改。例如,我们可以使用 upper 过滤器将字符串转换为大写。

def filter_view(request):
    context = {
        'text': 'hello world'
    }
    return render(request, 'filter.html', context)

filter.html 模板中:

<!DOCTYPE html>
<html>
<head>
    <title>Filter Example</title>
</head>
<body>
    <p>Original text: {{ text }}</p>
    <p>Uppercase text: {{ text|upper }}</p>
</body>
</html>

在上述代码中,{{ text|upper }} 使用 upper 过滤器将 text 变量的值转换为大写。

模板标签

控制结构标签

  1. if 标签if 标签用于在模板中进行条件判断。
def condition_view(request):
    is_logged_in = True
    context = {
        'is_logged_in': is_logged_in
    }
    return render(request, 'condition.html', context)

condition.html 模板中:

<!DOCTYPE html>
<html>
<head>
    <title>Condition Example</title>
</head>
<body>
    {% if is_logged_in %}
        <p>Welcome, user!</p>
    {% else %}
        <p>Please log in.</p>
    {% endif %}
</body>
</html>

在上述代码中,根据 is_logged_in 变量的值显示不同的内容。

  1. for 标签for 标签用于在模板中进行循环。
def loop_view(request):
    fruits = ['apple', 'banana', 'cherry']
    context = {
        'fruits': fruits
    }
    return render(request, 'loop.html', context)

loop.html 模板中:

<!DOCTYPE html>
<html>
<head>
    <title>Loop Example</title>
</head>
<body>
    <ul>
    {% for fruit in fruits %}
        <li>{{ fruit }}</li>
    {% endfor %}
    </ul>
</body>
</html>

在上述代码中,通过 for 标签遍历 fruits 列表并显示每个水果名称。

包含标签

include 标签用于在一个模板中包含另一个模板的内容。假设我们有一个 header.html 模板:

<!DOCTYPE html>
<html>
<head>
    <title>My Site</title>
</head>
<body>
    <header>
        <h1>Welcome to My Site</h1>
    </header>

index.html 模板中可以这样包含:

{% include 'header.html' %}
<div>
    <p>This is the main content of the page.</p>
</div>

这样可以将 header.html 的内容包含到 index.html 中,提高代码的复用性。

模板继承

模板继承是 Django 模板机制的一个强大特性,它允许我们创建一个基础模板,然后其他模板可以继承这个基础模板并覆盖其中的部分内容。

创建基础模板

创建一个 base.html 模板:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}Default Title{% endblock %}</title>
    <link rel="stylesheet" href="{% static'main.css' %}">
</head>
<body>
    <header>
        <h1>My Site</h1>
    </header>
    <div id="content">
        {% block content %}
        This is the default content.
        {% endblock %}
    </div>
    <footer>
        <p>&copy; 2024 My Company</p>
    </footer>
</body>
</html>

在上述 base.html 模板中,{% block title %}{% block content %} 定义了两个块,子模板可以覆盖这些块的内容。{% static'main.css' %} 用于引用静态文件。

创建子模板

创建一个 about.html 子模板:

{% extends 'base.html' %}

{% block title %}About Us{% endblock %}

{% block content %}
    <h2>About Our Company</h2>
    <p>We are a leading company in the industry...</p>
{% endblock %}

在上述 about.html 模板中,通过 {% extends 'base.html' %} 声明继承自 base.html。然后覆盖了 titlecontent 块,从而实现了特定页面的定制。

静态文件处理

在 Django 项目中,静态文件(如 CSS、JavaScript、图像等)的管理是非常重要的。

配置静态文件路径

在项目的 settings.py 文件中进行如下配置:

STATIC_URL ='static/'
STATICFILES_DIRS = [
    BASE_DIR /'static'
]
STATIC_ROOT = BASE_DIR /'staticfiles'

在上述配置中,STATIC_URL 定义了静态文件在浏览器中访问的 URL 前缀。STATICFILES_DIRS 包含了项目中静态文件的查找目录,这里设置为项目根目录下的 static 目录。STATIC_ROOT 是在部署时用于收集所有静态文件的目录。

引用静态文件

在模板中引用静态文件,如前面在 base.html 模板中引用 CSS 文件:

<link rel="stylesheet" href="{% static'main.css' %}">

{% static'main.css' %} 会根据 STATIC_URLSTATICFILES_DIRS 的配置找到对应的 main.css 文件,并生成正确的 URL。

总结视图与模板机制的协同工作

Django 的视图与模板机制紧密协同,视图负责处理业务逻辑,获取数据并传递给模板,而模板负责将数据以合适的格式呈现给用户。通过合理地使用视图函数、URL 映射、模板变量、标签以及静态文件处理等功能,我们能够构建出功能强大、易于维护的 Web 应用程序。在实际开发中,根据项目的需求灵活运用这些机制,能够提高开发效率,并且使得代码结构更加清晰,便于团队协作和后期维护。例如,在一个电商项目中,视图可以处理商品查询、购物车操作等逻辑,然后将商品信息、用户购物车数据等传递给模板,模板则将这些数据以美观的界面展示给用户,同时通过静态文件处理,引入 CSS 和 JavaScript 来增强用户界面的交互性和美观度。