Django多模型CRUD优化:无需为每个操作编写视图与模板?
不用重复写!Django多模型CRUD的简便实现方式
当然不需要为每个模型的每个CRUD操作都单独写视图函数和模板,有几种高效的方案可以大幅减少重复代码:
1. 用Django内置的通用类视图(Class-Based Views)
Django自带了一系列封装好的通用视图,专门用来处理CRUD场景,你只需要指定模型和少量配置,就能快速实现功能,甚至可以复用模板。
示例代码:
在views.py中,为不同模型复用通用视图:
from django.views.generic import ListView, CreateView, UpdateView, DeleteView from django.urls import reverse_lazy from .models import Employee, Department # 假设还有Department模型 # 提取通用配置作为基类 class BaseCRUD: success_url = reverse_lazy('home') # 操作成功后的跳转地址,可按需调整 fields = '__all__' # 使用模型所有字段生成表单 # Employee模型的CRUD class EmployeeList(BaseCRUD, ListView): model = Employee template_name = 'generic/list.html' # 通用列表模板 class EmployeeCreate(BaseCRUD, CreateView): model = Employee template_name = 'generic/form.html' # 通用表单模板 class EmployeeUpdate(BaseCRUD, UpdateView): model = Employee template_name = 'generic/form.html' class EmployeeDelete(BaseCRUD, DeleteView): model = Employee template_name = 'generic/delete.html' # Department模型直接复用基类,只需修改model class DepartmentList(BaseCRUD, ListView): model = Department template_name = 'generic/list.html' class DepartmentCreate(BaseCRUD, CreateView): model = Department template_name = 'generic/form.html'
通用模板示例:
generic/list.html(适配所有模型的列表页面):
<h1>{{ model._meta.verbose_name_plural|title }}</h1> <ul> {% for item in object_list %} <li>{{ item }} <a href="{% url 'update' model_name=model._meta.model_name pk=item.pk %}">编辑</a> <a href="{% url 'delete' model_name=model._meta.model_name pk=item.pk %}">删除</a> </li> {% endfor %} </ul> <a href="{% url 'create' model_name=model._meta.model_name %}">添加新{{ model._meta.verbose_name }}</a>
generic/form.html(适配创建/更新操作):
<h1>{% if object %}编辑{{ object }}{% else %}添加新{{ model._meta.verbose_name }}{% endif %}</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">保存</button> </form> <a href="{% url 'list' model_name=model._meta.model_name %}">返回列表</a>
2. 自定义通用CRUD视图(单视图处理所有模型)
如果想更极致地复用,你可以写一个动态视图,根据URL传入的模型名称,自动处理对应的CRUD操作,完全不用为每个模型写视图。
示例代码:
from django.shortcuts import render, redirect from django.forms import modelform_factory from .models import Employee, Department # 映射模型名称到模型类,避免不安全的动态导入 MODEL_MAP = { 'employee': Employee, 'department': Department, } def generic_crud(request, model_name, pk=None): model = MODEL_MAP.get(model_name) if not model: return redirect('home') # 动态生成对应模型的表单 FormClass = modelform_factory(model, fields='__all__') instance = model.objects.get(pk=pk) if pk else None if request.method == 'POST': form = FormClass(request.POST, instance=instance) if form.is_valid(): form.save() return redirect('generic_list', model_name=model_name) else: form = FormClass(instance=instance) context = { 'form': form, 'model': model, 'object': instance } return render(request, 'generic/form.html', context) def generic_list(request, model_name): model = MODEL_MAP.get(model_name) if not model: return redirect('home') context = { 'object_list': model.objects.all(), 'model': model } return render(request, 'generic/list.html', context) def generic_delete(request, model_name, pk): model = MODEL_MAP.get(model_name) if not model: return redirect('home') instance = model.objects.get(pk=pk) if request.method == 'POST': instance.delete() return redirect('generic_list', model_name=model_name) return render(request, 'generic/delete.html', {'object': instance, 'model': model})
对应的URL配置:
from django.urls import path from . import views urlpatterns = [ path('<str:model_name>/', views.generic_list, name='generic_list'), path('<str:model_name>/create/', views.generic_crud, name='generic_create'), path('<str:model_name>/<int:pk>/', views.generic_crud, name='generic_update'), path('<str:model_name>/<int:pk>/delete/', views.generic_delete, name='generic_delete'), ]
3. 直接用Django Admin(零代码CRUD)
如果只是需要后台管理的CRUD功能,Django Admin是最省事的选择——只需要在admin.py中注册模型,就能直接使用完整的CRUD界面,完全不用写视图和模板:
from django.contrib import admin from .models import Employee, Department admin.site.register(Employee) admin.site.register(Department)
启动项目后访问/admin,就能对所有注册的模型进行CRUD操作。
总结
不管是用内置通用视图、自定义动态视图,还是直接用Admin,都能避免重复编写大量的视图和模板代码。其中自定义动态视图可以做到一个视图处理所有模型的CRUD,配合通用模板,20个模型也只需要一套核心代码就能搞定。
内容的提问来源于stack exchange,提问作者PeroML
相关产品推荐
相关产品推荐

