with tutorial latest framework español desde con cero applications python django inheritance django-models

python - tutorial - cómo anular el nombre detallado de un campo de modelo de superclase en django



tutorial django (4)

Digamos que tengo un modelo Foo que hereda de 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

En la clase Foo, me gustaría sobrescribir el nombre detallado del campo de nombre de SuperFoo. ¿Puedo? De lo contrario, ¿es la mejor opción establecer una etiqueta dentro de la definición del formulario modelo para que se muestre en una plantilla?


Eche un vistazo a cómo lo hace Django-CMS, anulan el campo db_table en los modelos que heredan de CMSPlugin . Los conceptos básicos (que también uso para mis propias cosas) se reducen a:

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

Puede agregar algunas comprobaciones, por ejemplo, solo actualizar para las subclases (no el tipo directo), o solo actualizar si el valor no está personalizado.


Su mejor opción sería establecer / cambiar la etiqueta en el formulario mismo. Hacer referencia al campo de name del modelo Foo (por ejemplo, buscándolo en Foo._meta.fields ) en realidad le dará una referencia al campo de name de SuperFoo , por lo que cambiar su nombre verbose_name lo cambiará en ambos modelos.

Además, agregar un campo de name a la clase Foo tampoco funcionará, because ...

La anulación de campos en un modelo principal genera dificultades en áreas como la inicialización de nuevas instancias (especificando qué campo se está inicializando en el Model.__init__ ) y la serialización. Estas son características que la herencia de clases de Python normal no tiene que tratar de la misma manera, por lo que la diferencia entre la herencia del modelo Django y la herencia de la clase Python no es meramente arbitraria.


Teniendo en cuenta la advertencia de que la modificación de Foo._meta.fields también afectará a la superclase, y por lo tanto solo es realmente útil si la superclase es abstracta, he envuelto la respuesta. @Gerry se dio por vencido como decorador de clase reutilizable:

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

Úselo así:

@modify_fields(timestamp={ ''verbose_name'': ''Available From'', ''help_text'': ''Earliest date you can book this''}) class Purchase(BaseOrderItem): pass

El ejemplo anterior cambia el verbose_name y help_text para el campo heredado ''timestamp''. Puede pasar tantos argumentos de palabras clave como campos que desee modificar.


Un simple truco que he usado es:

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''