Django 视图

以下是用中文详细讲解 Django 视图(Views)的指南,涵盖视图的作用、类型、创建方法、常用模式、与模板和模型的集成,以及最佳实践。我会保持简洁清晰,适合初学者和进阶用户,并提供实用示例,关键代码将包裹在 ““` 标签中以生成 artifact。你提到需要 artifact,因此我会确保代码示例清晰标注。如果你有特定问题或需要更深入的内容,请随时告知!


什么是 Django 视图?

Django 视图是处理 HTTP 请求并返回响应的 Python 函数或类,负责业务逻辑,连接模型(数据)和模板(展示)。视图是 Django MTV 架构中的“V”(View)部分。

  • 作用
  • 接收用户请求(如 GET、POST)。
  • 处理数据(查询数据库、验证表单等)。
  • 返回响应(如 HTML 页面、JSON、重定向)。
  • 特点
  • 支持函数视图(Function-Based Views, FBV)和类视图(Class-Based Views, CBV)。
  • 与 URL 路由绑定,处理特定路径的请求。
  • 灵活集成模型、表单和模板。

1. 视图类型

Django 支持两种主要视图类型:函数视图(FBV)类视图(CBV)

1.1 函数视图(FBV)

  • 定义:普通的 Python 函数,接受 request 参数,返回 HttpResponse 或其他响应。
  • 优点:简单直观,适合小型或特定逻辑。
  • 缺点:复杂逻辑时代码可能冗长,复用性较差。

1.2 类视图(CBV)

  • 定义:继承 Django 提供的类(如 ViewTemplateView),通过方法处理请求。
  • 优点:支持继承和复用,内置通用功能(如列表、详情视图)。
  • 缺点:初学者可能觉得抽象,学习曲线稍陡。

2. 创建视图

假设我们有一个应用 myapp,包含模型 ItemCategory,以下展示如何创建视图。

模型定义(参考)

myapp/models.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Item(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

2.1 函数视图(FBV)

示例:myapp/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from .models import Item, Category
from .forms import ItemForm

# 简单视图:返回文本响应
def hello(request):
    return HttpResponse("Hello, Django!")

# 列表视图:显示所有商品
def item_list(request):
    items = Item.objects.select_related('category').all()
    return render(request, 'myapp/item_list.html', {'items': items})

# 详情视图:显示单个商品
def item_detail(request, pk):
    item = get_object_or_404(Item, pk=pk)
    return render(request, 'myapp/item_detail.html', {'item': item})

# 创建视图:处理表单
def item_create(request):
    if request.method == 'POST':
        form = ItemForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('item_list')
    else:
        form = ItemForm()
    return render(request, 'myapp/item_form.html', {'form': form})


from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from .models import Item, Category
from .forms import ItemForm

简单视图:返回文本响应

def hello(request):
return HttpResponse(“Hello, Django!”)

列表视图:显示所有商品

def item_list(request):
items = Item.objects.select_related(‘category’).all()
return render(request, ‘myapp/item_list.html’, {‘items’: items})

详情视图:显示单个商品

def item_detail(request, pk):
item = get_object_or_404(Item, pk=pk)
return render(request, ‘myapp/item_detail.html’, {‘item’: item})

创建视图:处理表单

def item_create(request):
if request.method == ‘POST’:
form = ItemForm(request.POST)
if form.is_valid():
form.save()
return redirect(‘item_list’)
else:
form = ItemForm()
return render(request, ‘myapp/item_form.html’, {‘form’: form})
“`python
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from .models import Item, Category
from .forms import ItemForm

简单视图:返回文本响应

def hello(request):
return HttpResponse(“Hello, Django!”)

列表视图:显示所有商品

def item_list(request):
items = Item.objects.select_related(‘category’).all()
return render(request, ‘myapp/item_list.html’, {‘items’: items})

详情视图:显示单个商品

def item_detail(request, pk):
item = get_object_or_404(Item, pk=pk)
return render(request, ‘myapp/item_detail.html’, {‘item’: item})

创建视图:处理表单

def item_create(request):
if request.method == ‘POST’:
form = ItemForm(request.POST)
if form.is_valid():
form.save()
return redirect(‘item_list’)
else:
form = ItemForm()
return render(request, ‘myapp/item_form.html’, {‘form’: form})

- **说明**:
  - `hello`:返回简单的 `HttpResponse`。
  - `item_list`:查询所有商品,渲染模板。
  - `item_detail`:使用 `get_object_or_404` 获取单条记录,处理 404 错误。
  - `item_create`:处理 GET(显示表单)和 POST(保存数据)请求。

#### 2.2 类视图(CBV)
##### 示例:`myapp/views.py`

python
from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
from .models import Item
from .forms import ItemForm

列表视图

class ItemListView(ListView):
model = Item
template_name = ‘myapp/item_list.html’
context_object_name = ‘items’

def get_queryset(self):
    return Item.objects.select_related('category').all()

详情视图

class ItemDetailView(DetailView):
model = Item
template_name = ‘myapp/item_detail.html’
context_object_name = ‘item’

创建视图

class ItemCreateView(CreateView):
model = Item
form_class = ItemForm
template_name = ‘myapp/item_form.html’
success_url = reverse_lazy(‘item_list’)

- **说明**:
  - `ListView`:显示对象列表,自动处理分页。
  - `DetailView`:显示单个对象详情。
  - `CreateView`:处理表单创建,自动保存。
  - `context_object_name`:自定义模板中的对象名称。
  - `reverse_lazy`:延迟解析 URL,避免加载顺序问题。

---

### 3. 模板
以下是视图使用的模板示例。

#### 示例:`myapp/templates/myapp/item_list.html`

html
{% extends ‘base.html’ %}

{% block content %}

商品列表

添加商品

  • {{ item.name }} – ¥{{ item.price }} ({{ item.category.name }})
  • 暂无商品

{% endblock %}

#### 示例:`myapp/templates/myapp/item_detail.html`

html
{% extends ‘base.html’ %}

{% block content %}

{{ item.name }}

价格:¥{{ item.price }}

分类:{{ item.category.name }}

描述:{{ item.description|default:”无描述” }}
返回列表
{% endblock %}

#### 示例:`myapp/templates/myapp/item_form.html`

html
{% extends ‘base.html’ %}

{% block content %}

添加商品

{% csrf_token %} {{ form.as_p }} 保存
取消
{% endblock %}

#### 基础模板:`templates/base.html`

html

{% block title %}我的网站{% endblock %} 首页 {% block content %} {% endblock %} © 2025 我的网站

---

### 4. URL 配置
视图需通过 URL 路由绑定到特定路径。

#### 示例:`myapp/urls.py`

python
from django.urls import path
from . import views

urlpatterns = [
path(”, views.hello, name=’hello’),
path(‘items/’, views.item_list, name=’item_list’),
path(‘items//’, views.item_detail, name=’item_detail’),
path(‘items/create/’, views.item_create, name=’item_create’),
# 类视图路由
path(‘items/list/’, views.ItemListView.as_view(), name=’item_list_cbv’),
path(‘items//detail/’, views.ItemDetailView.as_view(), name=’item_detail_cbv’),
path(‘items/create/cbv/’, views.ItemCreateView.as_view(), name=’item_create_cbv’),
]

#### 项目 `urls.py`

python
from django.urls import path, include

urlpatterns = [
path(”, include(‘myapp.urls’)),
]

---

### 5. 表单(参考)
用于 `item_create` 视图的表单。

#### 示例:`myapp/forms.py`

python
from django import forms
from .models import Item

class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = [‘name’, ‘price’, ‘category’, ‘description’]
labels = {
‘name’: ‘商品名称’,
‘price’: ‘价格’,
‘category’: ‘分类’,
‘description’: ‘描述’,
}
widgets = {
‘description’: forms.Textarea(attrs={‘rows’: 4}),
}

def clean_price(self):
    price = self.cleaned_data['price']
    if price <= 0:
        raise forms.ValidationError('价格必须大于 0')
    return price
---

### 6. 高级功能
#### 6.1 JSON 响应
返回 JSON 数据,适合 API 或 AJAX 请求。

##### 示例:`myapp/views.py`

python
from django.http import JsonResponse

def item_json(request):
items = Item.objects.values(‘id’, ‘name’, ‘price’)
return JsonResponse(list(items), safe=False)

- **说明**:
  - `values()`:返回字典列表。
  - `safe=False`:允许非字典数据。

#### 6.2 权限控制
限制视图访问,仅允许登录用户。

##### 示例:`myapp/views.py`

python
from django.contrib.auth.decorators import login_required

@login_required
def restricted_view(request):
return render(request, ‘myapp/restricted.html’, {‘user’: request.user})

- **CBV 权限**:

python
from django.contrib.auth.mixins import LoginRequiredMixin

class RestrictedView(LoginRequiredMixin, TemplateView):
template_name = ‘myapp/restricted.html’

#### 6.3 分页
`ListView` 内置分页功能。

##### 示例:

python
class ItemListView(ListView):
model = Item
template_name = ‘myapp/item_list.html’
context_object_name = ‘items’
paginate_by = 10 # 每页 10 条

##### 模板:

html
{% for item in items %}
{{ item.name }}
{% endfor %}

{% if page_obj.has_previous %} 上一页 {% endif %} 第 {{ page_obj.number }} 页 / 共 {{ paginator.num_pages }} 页 {% if page_obj.has_next %} 下一页 {% endif %}

---

### 7. 最佳实践
1. **逻辑分离**:
   - 视图负责处理请求和响应,复杂逻辑放在模型或工具函数中。
   - 使用 `ModelForm` 简化数据库操作。

2. **错误处理**:
   - 使用 `get_object_or_404` 或 `try-except` 处理不存在的对象。
   - 提供用户友好的错误页面(自定义 404/500 模板)。

3. **复用代码**:
   - CBV 通过继承复用通用逻辑。
   - 使用装饰器或混入(mixins)添加功能。

4. **安全性**:
   - 始终包含 `{% csrf_token %}` 处理 POST 请求。
   - 使用 `request.user` 检查认证状态。

5. **性能优化**:
   - 使用 `select_related` 和 `prefetch_related` 减少数据库查询:
     ```python
     items = Item.objects.select_related('category').all()
     ```
   - 缓存视图或查询结果:
     ```python
     from django.views.decorators.cache import cache_page

     @cache_page(60 * 15)  # 缓存 15 分钟
     def item_list(request):
         ...
     ```

---

### 8. 常见问题
1. **视图未响应**:
   - 检查 `urls.py` 是否正确映射。
   - 确保模板路径正确。

2. **404 错误**:
   - 确认 URL 模式和参数(如 `pk`)匹配。
   - 使用 `get_object_or_404` 替代手动查询。

3. **表单提交失败**:
   - 检查 `request.method` 逻辑。
   - 确保 `form.is_valid()` 和 `form.errors` 正确处理。

4. **性能慢**:
   - 使用 Django Debug Toolbar 分析查询。
   - 优化数据库查询或启用缓存。

---

### 9. 运行项目
1. 确保模型迁移:

bash
python manage.py makemigrations
python manage.py migrate

2. 启动服务器:

bash
python manage.py runserver
“`

  1. 访问:
  • 简单视图:http://127.0.0.1:8000/
  • 商品列表:http://127.0.0.1:8000/items/
  • 添加商品:http://127.0.0.1:8000/items/create/
  • CBV 列表:http://127.0.0.1:8000/items/list/

总结

Django 视图通过 FBV 和 CBV 提供灵活的请求处理方式,结合模型、表单和模板,实现动态 Web 应用。FBV 简单直观,适合快速开发;CBV 复用性强,适合复杂项目。遵循最佳实践(如分离逻辑、优化查询)可以提高代码质量和性能。

如果你需要更复杂的视图示例(如 REST API、自定义混入)、特定功能的深入讲解,或调试视图问题的方法,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注