Django admin:继承基类字段,以便用于在保存时设置模型的字段

2024-09-30 00:37:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模型CakeBakedCake有一个指向Cake的外键,并包含一个datetime类型的created_utc字段

假设我有模型CupCakeLemonCakeCheeseCake,每个模型都有一个外键字段baked_cake来建模BakedCake,因为它们共享这个行为和许多其他行为,它们都继承自同一基类BaseModel

现在,在CupCakeLemonCakeCheeseCake的Django管理界面中,我们希望显示一个Cake而不是BakedCake的列表,因此该列表要短得多,更容易选择。因此,我们宁愿显示一个cake列表,然后一旦用户选择了一个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的字段,使其派生类也继承这些更改

总结

我想做的不是在管理界面中显示原始模型的字段,而是显示另一个模型的备用字段,然后在保存时使用业务逻辑选择适当的原始字段。这需要在多个模型中发生,因此需要从基础模型继承逻辑

注意:使用Django 3


Tags: 模型formfieldsadminmodelsbakedclassbasemodel
1条回答
网友
1楼 · 发布于 2024-09-30 00:37:40

这个模型管理类的设置肯定有效(至少在Django3.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)

示例屏幕截图

Example Screenshot

注意:别忘了用你的逻辑完成get_baked_cake_instance(...)方法

相关问题 更多 >

    热门问题