Django如何合并ListView等多个通用视图为单个类精简重复代码
Django 多模型CRUD重复代码重构方案
你需要的效果可以通过自定义统一CRUD基类视图 + 正则路由分发实现,具体实现步骤如下:
第一步:编写CRUD基础视图类
在views.py中先实现可复用的基类,内部自动根据请求参数分发到对应的通用视图处理,同时统一挂载你需要的装饰器:
from django.views.generic import View from django.views.generic import ListView, CreateView, UpdateView, DeleteView from django.utils.decorators import method_decorator # 替换为你自己的装饰器列表,比如登录验证、权限校验等 decorators = [login_required] class CRUDView(View): # 子类只需要覆盖以下字段即可自定义逻辑,不需要重复写视图代码 model = None form_class = None list_template = None form_template = None success_redirect_url = None @method_decorator(decorators, name='dispatch') def dispatch(self, request, *args, **kwargs): action = kwargs.get("action") obj_id = kwargs.get("id") # 默认跳转路径取当前模型的列表页 base_url = f"/{self.model._meta.model_name}/" success_url = self.success_redirect_url or base_url # 新增逻辑 if action == "add": view = CreateView.as_view( model=self.model, form_class=self.form_class, template_name=self.form_template or f"{self.model._meta.model_name}_form.html", success_url=success_url ) # 修改逻辑 elif action == "update" and obj_id: view = UpdateView.as_view( model=self.model, form_class=self.form_class, template_name=self.form_template or f"{self.model._meta.model_name}_form.html", success_url=success_url, pk_url_kwarg="id" ) # 删除逻辑 elif action == "delete" and obj_id: view = DeleteView.as_view( model=self.model, success_url=success_url, pk_url_kwarg="id" ) # 默认返回列表页 else: view = ListView.as_view( model=self.model, template_name=self.list_template or f"{self.model._meta.model_name}_list.html" ) return view(request, *args, **kwargs)
第二步:定义各模型的视图类
写完基类后,每个模型的视图只需要几行代码就可以实现全部CRUD能力,完全符合你预期的写法:
# 客户模型视图 class CustomerView(CRUDView): model = CustomerModel # 有自定义需求就加对应字段,比如指定表单类:form_class = CustomerForm # 员工模型视图 class EmployeeView(CRUDView): model = EmployeeModel # 工人模型视图 class WorkerView(CRUDView): model = WorkerModel
第三步:简化路由配置
在urls.py中用正则路由,每个模型只需要一行配置就覆盖全部四个CRUD路径:
from django.urls import re_path from . import views urlpatterns = [ # 每个模型一行路由,自动匹配列表、新增、修改、删除四种请求 re_path(r'^customer/(?:(?P<action>add|update|delete)/?(?:(?P<id>\d+)/?)?)?$', views.CustomerView.as_view(), name='customer-crud'), re_path(r'^employee/(?:(?P<action>add|update|delete)/?(?:(?P<id>\d+)/?)?)?$', views.EmployeeView.as_view(), name='employee-crud'), re_path(r'^worker/(?:(?P<action>add|update|delete)/?(?:(?P<id>\d+)/?)?)?$', views.WorkerView.as_view(), name='worker-crud'), ]
扩展说明
如果某个模型需要定制逻辑,比如列表页要加过滤、表单要加额外逻辑,直接在对应子类重写方法或者覆盖字段即可,不需要修改基类代码。
内容的提问来源于stack exchange,提问作者devnext
相关产品推荐
相关产品推荐

