假设我有一个继承自SuperFoo的模型Foo:
class SuperFoo(models.Model):
name = models.CharField('name of SuperFoo instance', max_length=50)
...
class Foo(SuperFoo):
... # do something that changes verbose_name of name field of SuperFoo
在Foo类中,我想覆盖SuperFoo名称字段的verbose_name。我可以吗?如果没有,是在模型表单定义中设置标签以使其显示在模板中的最佳选择吗?
答案 0 :(得分:51)
我使用的一个简单的黑客是:
class SuperFoo(models.Model):
name = models.CharField('name of SuperFoo instance', max_length=50)
...
class Meta:
abstract = True
class Foo(SuperFoo):
... # do something that changes verbose_name of name field of SuperFoo
Foo._meta.get_field('name').verbose_name = 'Whatever'
答案 1 :(得分:10)
请记住,修改Foo._meta.fields也会影响超类 - 因此只有在超类是抽象的时候才真正有用,我已经将@Gerry放弃的答案包装成可重用的类装饰器:
def modify_fields(**kwargs):
def wrap(cls):
for field, prop_dict in kwargs.items():
for prop, val in prop_dict.items():
setattr(cls._meta.get_field(field), prop, val)
return cls
return wrap
像这样使用:
@modify_fields(timestamp={
'verbose_name': 'Available From',
'help_text': 'Earliest date you can book this'})
class Purchase(BaseOrderItem):
pass
上面的示例更改了继承字段' timestamp'的verbose_name和help_text。您可以传入与要修改的字段一样多的关键字参数。
答案 2 :(得分:5)
您最好的选择是在表单中设置/更改标签。参考name
模型的Foo
字段(例如,在Foo._meta.fields
中查找),实际上会为您提供name
SuperFoo
字段的引用},因此更改其verbose_name
将在两个模型中更改它。
此外,向name
课程添加Foo
字段也不起作用,because ...
覆盖父模型中的字段 导致诸如此类领域的困难 初始化新实例(指定 哪个领域正在进行中
Model.__init__
)和序列化。 这些是普通Python的功能 类继承不必处理 以完全相同的方式,所以 Django模型之间的区别 继承和Python类 继承不仅仅是武断的。
答案 3 :(得分:5)
看看Django-CMS如何做到这一点,它们会覆盖继承自db_table
的模型中的CMSPlugin
字段。基础知识(我也用于我自己的东西)归结为:
class SuperFooMetaClass(ModelBase):
def __new__(cls, name, bases, attrs):
new_class = super(SuperFooMetaClass, cls).__new__(cls, name, bases, attrs)
new_class._meta.verbose_name = "...." # perhaps only if not customized
return new_class
class SuperFoo(models.Model):
__metaclass__ = SuperFooMetaClass
....
您可以添加一些支票,例如仅更新子类(不是直接类型),或仅在未自定义值时更新。
答案 4 :(得分:0)
我有不同的子类,它们是从同一基类派生的。而且我只关心Django Admin界面中的表单视图。
对我而言唯一有效的解决方案是自定义Django Admin界面并在此处设置verbose_name(或help_text):
class FooAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
form.base_fields['name'].verbose_name = "my verbose name"
return form
admin.site.register(models.Foo, FooAdmin)