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
相关产品推荐
相关产品推荐

