как переопределить подробное имя поля модели суперкласса в Django - PullRequest
27 голосов
/ 29 мая 2009

Допустим, у меня есть модель Foo, которая наследуется от SuperFoo:

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 я хотел бы переопределить verbose_name поля имени SuperFoo. Могу я? Если нет, то лучше ли устанавливать метку внутри определения формы модели, чтобы она отображалась в шаблоне?

Ответы [ 4 ]

51 голосов
/ 30 мая 2009

Простой взлом, который я использовал:

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'
10 голосов
/ 29 июня 2014

Принимая во внимание предостережение о том, что изменение 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

В приведенном выше примере изменяются verbose_name и help_text для унаследованного поля 'timestamp'. Вы можете передать столько аргументов ключевого слова, сколько есть полей, которые вы хотите изменить.

5 голосов
/ 21 июня 2011

Посмотрите, как 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

    ....

Вы можете добавить некоторые проверки, например, обновлять только для подклассов (не прямой тип) или обновлять, только если значение не настроено.

5 голосов
/ 30 мая 2009

Лучше всего было бы установить / изменить метку в самой форме. Обращение к полю name модели Foo (например, просмотрев его в Foo._meta.fields) фактически даст вам ссылку на поле name SuperFoo, поэтому изменение его verbose_name изменит это в обеих моделях.

Кроме того, добавление поля name в класс Foo также не будет работать, , поскольку ...

Переопределение полей в родительской модели приводит к трудностям в таких областях, как инициализация новых экземпляров (указание какое поле вводится в Model.__init__) и сериализация. Это особенности, которые нормальный Python наследование классов не должно иметь дело с таким же образом, так что Разница между моделью Джанго наследование и класс Python наследование не просто произвольно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...