You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:21:02