You need to enable JavaScript to run this app. Django如何创建Mixin为模型、视图及管理后台设置通用属性?
优惠活动
大模型
产品
解决方案
定价
更多

Django如何创建Mixin为模型、视图及管理后台设置通用属性?

实现方案

你之前遇到的子类无法重写get_form的问题,核心是把审计字段赋值逻辑和表单结构处理逻辑耦合在了一起,我们将赋值逻辑转移到form_valid方法中实现完全解耦,同时遵循Mixin的设计规范,即可解决问题。

1. CBV 通用审计字段Mixin

该Mixin不需要继承任何视图类,仅实现核心的赋值逻辑,完全不干扰子类自定义表单相关方法:

from django.views.generic.edit import FormMixin

class AuditFieldsMixin(FormMixin):
    def form_valid(self, form):
        # 先获取未提交的实例对象
        self.object = form.save(commit=False)
        
        # 仅新增场景赋值created_by
        if not self.object.pk:
            # 可按需增加登录判断,适配公开表单场景
            if self.request.user.is_authenticated:
                self.object.created_by = self.request.user
        
        # 所有保存场景都更新updated_by
        if self.request.user.is_authenticated:
            self.object.updated_by = self.request.user
        
        # 保存实例
        self.object.save()
        # 保存多对多关联字段(如果表单存在多对多字段时必须调用)
        form.save_m2m()
        
        # 调用父类原生逻辑,不影响原有流程
        return super().form_valid(form)

使用方式

继承时将Mixin放在原生视图类的前面,保证方法解析顺序优先调用Mixin逻辑,子类可任意重写get_form等方法,完全不受影响:

from django.views.generic import CreateView, UpdateView
from .models import ModelX
from .forms import ModelXForm

# 创建视图
class ModelXCreate(AuditFieldsMixin, CreateView):
    model = ModelX
    form_class = ModelXForm

    # 可自由重写get_form,不会影响审计字段赋值
    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        # 自定义表单逻辑示例
        form.fields['status'].initial = 1
        return form

# 更新视图同理
class ModelXUpdate(AuditFieldsMixin, UpdateView):
    model = ModelX
    form_class = ModelXForm

2. Admin后台审计字段Mixin

通过重写save_model方法实现逻辑,和视图层逻辑保持一致:

class AuditFieldsAdminMixin:
    def save_model(self, request, obj, form, change):
        # change为False代表是新增对象场景
        if not change:
            obj.created_by = request.user
        # 所有保存场景都更新updated_by
        obj.updated_by = request.user
        # 调用父类原生保存逻辑
        super().save_model(request, obj, form, change)

使用方式

同样将Mixin放在原生ModelAdmin前面继承即可:

from django.contrib import admin
from .models import ModelX

@admin.register(ModelX)
class ModelXAdmin(AuditFieldsAdminMixin, admin.ModelAdmin):
    # 自定义Admin配置,无任何限制
    list_display = ['title', 'created_at', 'created_by', 'updated_at', 'updated_by']
    search_fields = ['title']

注意事项

  • 所有使用以上Mixin的模型必须先继承你定义的Timestampable抽象模型,确保存在对应的审计字段
  • 若存在无需登录即可提交的公开表单,可自行调整用户校验逻辑,避免赋值报错
  • 继承顺序必须保证自定义Mixin在原生类之前,否则Mixin逻辑不会生效

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 02:51:03