代码之家  ›  专栏  ›  技术社区  ›  shanyu

如何重写django中超类模型字段的详细名称

  •  27
  • shanyu  · 技术社区  · 15 年前

    假设我有一个从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的name字段的verbose_name。我可以吗?如果不是,在模型表单定义内设置标签以使其显示在模板中是最佳选项吗?

    4 回复  |  直到 6 年前
        1
  •  51
  •   chris Frisina    6 年前

    我使用的一个简单的黑客方法是:

    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'
    
        2
  •  10
  •   Andy Baker    10 年前

    考虑到修改foo.\u 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”的详细“名称”和“帮助”文本。您可以在需要修改的字段中传入任意多个关键字参数。

        3
  •  5
  •   Steef    15 年前

    您最好的选择是设置/更改表单本身的标签。指的是 name 领域 Foo 模型(例如通过查找 Foo._meta.fields )会给你一个参考 名称 领域 SuperFoo ,所以改变它 verbose_name 将在两种型号中进行更改。

    此外,添加 名称 字段到 课程也不起作用, because

    覆盖父模型中的字段 导致在以下领域出现困难 初始化新实例(指定 哪个字段正在初始化 Model.__init__ )和序列化。 这些是普通的python 类继承不需要处理 以同样的方式,所以 Django模型之间的差异 继承和python类 继承不仅仅是武断的。

        4
  •  5
  •   vdboor    13 年前

    看看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
    
        ....
    

    您可以添加一些检查,例如仅更新子类(而不是直接类型),或者仅在未自定义值时更新。