Django admin:继承基础 class 字段,以便它用于在保存时设置模型的字段
Django admin: inherit base class field such that it is used to set the model's field on save
我有模型Cake
。 BakedCake
有一个指向 Cake
的外键并包含一个 created_utc
日期时间类型的字段。
假设我有模型 CupCake
、LemonCake
、CheeseCake
,每个模型都有一个外键字段 baked_cake
到模型 BakedCake
,因为它们共享这个行为和许多其他行为,它们都继承自相同的基础 class BaseModel
.
现在,在 CupCake
、LemonCake
、CheeseCake
的 Django 管理界面中,我们希望显示 Cake
而不是 BakedCake
的列表s,因此列表更短,更容易 select。因此,我们宁愿显示 cake
的列表,然后一旦用户 select 编辑了 cake
,我们使用当前日期时间和商务逻辑来设置适当的 baked_caked
保存。
演示代码:
# --- models.py
class Cake(models.Model):
name = models.CharField("Bar name", max_length=200, unique=True)
class BakedCake(models.Model):
cake = models.ForeignKey(Cake, on_delete=models.PROTECT)
created_utc = models.DateTimeField()
class BaseModel(models.Model):
baked_cake = models.ForeignKey(BakedCake, on_delete=models.PROTECT)
# -- Lots of other common business logic here --
class CupCake(BaseModel):
custom_field = models.CharField("Example1", max_length=200, unique=True)
class LemonCake(BaseModel):
other_field = models.BooleanField("Example2", default=True, )
class CheeseCake(BaseModel):
another_field = SmallFloatField("Example3", )
# --- admin.py
class BaseAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs) # This form object does not have .fields attribute
form.fields = [x for x in form.fields if x != 'baked_cake']
form.fields += 'cake'
return form
@admin.register(CupCake)
class CupCakeAdmin(BaseAdmin):
pass
@admin.register(LemonCake)
class LemonCakeAdmin(BaseAdmin):
pass
@admin.register(CheeseCake)
class CheeseCakeAdmin(BaseAdmin):
pass
不幸的是 form.fields
在 form
对象上不存在。如何替换基础 ModelAdmin
class 的字段,使其派生的 class 也继承这些更改?
总结
我想做的不是在管理界面中显示原始模型的字段,而是显示另一个模型的备用字段,然后在保存时使用业务逻辑 select 适当的原始字段。这需要在多个模型中发生,因此需要从基础模型继承逻辑。
注意:使用 Django 3
模型管理的这种设置 class 绝对有效(至少在 Django 3.1 中)
from django.contrib import admin
from django import forms
from .models import Cake
class AbstractModelAdmin(admin.ModelAdmin):
def get_baked_cake_instance(self, cake):
return "something"
def get_form(self, request, obj=None, change=False, **kwargs):
form = forms.modelform_factory(self.model, exclude=("baked_cake",))
form.base_fields["cake"] = forms.ModelChoiceField(queryset=Cake.objects.all())
return form
def save_form(self, request, form, change):
model_instance = form.save(commit=False)
model_instance.baked_cake = self.get_baked_cake_instance(form.cleaned_data["cake"])
return model_instance
然后,注册您的模型,
admin.site.register(CupCake, AbstractModelAdmin)
admin.site.register(LemonCake, AbstractModelAdmin)
admin.site.register(CheeseCake, AbstractModelAdmin)
示例屏幕截图
注意:不要忘记用你的逻辑完成get_baked_cake_instance(...)
方法!!!
我有模型Cake
。 BakedCake
有一个指向 Cake
的外键并包含一个 created_utc
日期时间类型的字段。
假设我有模型 CupCake
、LemonCake
、CheeseCake
,每个模型都有一个外键字段 baked_cake
到模型 BakedCake
,因为它们共享这个行为和许多其他行为,它们都继承自相同的基础 class BaseModel
.
现在,在 CupCake
、LemonCake
、CheeseCake
的 Django 管理界面中,我们希望显示 Cake
而不是 BakedCake
的列表s,因此列表更短,更容易 select。因此,我们宁愿显示 cake
的列表,然后一旦用户 select 编辑了 cake
,我们使用当前日期时间和商务逻辑来设置适当的 baked_caked
保存。
演示代码:
# --- models.py
class Cake(models.Model):
name = models.CharField("Bar name", max_length=200, unique=True)
class BakedCake(models.Model):
cake = models.ForeignKey(Cake, on_delete=models.PROTECT)
created_utc = models.DateTimeField()
class BaseModel(models.Model):
baked_cake = models.ForeignKey(BakedCake, on_delete=models.PROTECT)
# -- Lots of other common business logic here --
class CupCake(BaseModel):
custom_field = models.CharField("Example1", max_length=200, unique=True)
class LemonCake(BaseModel):
other_field = models.BooleanField("Example2", default=True, )
class CheeseCake(BaseModel):
another_field = SmallFloatField("Example3", )
# --- admin.py
class BaseAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs) # This form object does not have .fields attribute
form.fields = [x for x in form.fields if x != 'baked_cake']
form.fields += 'cake'
return form
@admin.register(CupCake)
class CupCakeAdmin(BaseAdmin):
pass
@admin.register(LemonCake)
class LemonCakeAdmin(BaseAdmin):
pass
@admin.register(CheeseCake)
class CheeseCakeAdmin(BaseAdmin):
pass
不幸的是 form.fields
在 form
对象上不存在。如何替换基础 ModelAdmin
class 的字段,使其派生的 class 也继承这些更改?
总结
我想做的不是在管理界面中显示原始模型的字段,而是显示另一个模型的备用字段,然后在保存时使用业务逻辑 select 适当的原始字段。这需要在多个模型中发生,因此需要从基础模型继承逻辑。
注意:使用 Django 3
模型管理的这种设置 class 绝对有效(至少在 Django 3.1 中)
from django.contrib import admin
from django import forms
from .models import Cake
class AbstractModelAdmin(admin.ModelAdmin):
def get_baked_cake_instance(self, cake):
return "something"
def get_form(self, request, obj=None, change=False, **kwargs):
form = forms.modelform_factory(self.model, exclude=("baked_cake",))
form.base_fields["cake"] = forms.ModelChoiceField(queryset=Cake.objects.all())
return form
def save_form(self, request, form, change):
model_instance = form.save(commit=False)
model_instance.baked_cake = self.get_baked_cake_instance(form.cleaned_data["cake"])
return model_instance
然后,注册您的模型,
admin.site.register(CupCake, AbstractModelAdmin)
admin.site.register(LemonCake, AbstractModelAdmin)
admin.site.register(CheeseCake, AbstractModelAdmin)
示例屏幕截图
注意:不要忘记用你的逻辑完成get_baked_cake_instance(...)
方法!!!