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