2009-09-01 11 views
6

Je souhaite utiliser les propriétés de la classe Meta d'un modèle hérité pour configurer un champ défini dans un modèle abstrait situé plus haut dans l'arbre d'héritage:Impossible d'utiliser une classe Meta héritée du modèle Django pour configurer un champ défini dans un modèle abstrait hérité

class NamedModel(models.Model): 
    class Meta: 
     abstract = True 
     verbose_name = 'object' 

    name = models.CharField("Name", 
     max_length=200, 
     db_index=True, 
     help_text="A meaningful name for this %s." % Meta.verbose_name) 
     # see what I'm trying to do here? 
    ) 
    ... 

class OwnedModel(NamedModel): 
    class Meta(NamedModel.Meta): 
     verbose_name = 'owned object' 

Je voudrais que le texte d'aide sur le champ nom des formes OwnedModel dire «Un nom significatif pour cet objet appartenant. Mais ce n'est pas: le mot 'owned' est manquant, ce qui suggère que le verbose_name du NamedModel.Meta est utilisé lorsque le modèle est configuré, et non OwnedModel.Meta. Ce n'est pas tout à fait ce que j'attends du point de vue de l'héritage: existe-t-il un moyen de créer le champ où Meta.verbose_name fait référence à la valeur de la classe de modèle non-abstraite, pas à celle abstraite sur lequel le champ a été défini?

Ou suis-je daft?

(Cela peut sembler un exemple trivial, et il est: mais il est juste pour illustrer le point de quelque chose de plus important et complexe que je suis en train de faire)

Un grand merci à l'avance.

Répondre

1

Je pense que cela se produit car Meta.verbose_name est utilisé et NamedModel.name est créé lorsque la classe NamedModel est analysée. Plus tard, lorsque la classe OwnedModel est analysée, il n'y a aucune chance de changer quoi que ce soit.

Peut-être que vous pouvez définir la propriété help_text sur OwnedModel.name plus tard, mais cela peut également changer NamedModel.name. Dans des situations similaires, j'ai placé les parties variables dans l'attribut class du modèle (pas Meta), puis j'ai utilisé les méthodes/propriétés by run time pour générer les textes dont j'ai besoin.

+0

Oui, je pense que c'est ce. Après avoir suivi le flux, je suis plus clair sur le cycle de vie: les champs sont évalués lorsque la classe est analysée, donc l'héritage n'est pas pris en compte. Et j'ai essayé des attributs de classe en dehors de méta ... même problème bien sûr. Je suis heureux de remplacer les classes de champs et je peux utiliser cela (+ ce que vous suggérez) pour obtenir l'effet désiré. –

1

En fait, j'ai fini par faire ce qui suit. Le modèle de base reçoit une méthode de classe dynamic_field_definition(), qui peut être utilisée pour rafistoler les champs, l'argument cls étant la classe correcte (inheriting). Cela signifie que les attributs Meta de cette cls sont de cet enfant correct, pas la base d'origine. Puis, je câline cette méthode pour être appelée sur le signal class_prepared, de sorte que vous sachiez que tout est prêt.

class NamedModel(models.Model): 
    ... 
    @classmethod 
    def dynamic_field_definition(cls): 
     pass 

def dynamic_field_definition(sender, **kwargs): 
    if issubclass(sender, NamedModel): 
     sender.dynamic_field_definition() 
class_prepared.connect(dynamic_field_definition) 

ensuite les propriétés de champ qui varient selon la classe de modèle sont simplement reconfiguré par cette méthode de classe (ou plus probablement la méthode que redéfinie dans les classes dérivées).

C'est une façon légèrement hacky d'apporter un dernier petit peu de OO-ness aux modèles Django, mais ça marche bien pour mon but. Pourquoi n'essayez-vous pas de créer une classe?

2

class BaseNamedModelMeta: 
    abstract = True 
    verbose_name = "your text" 

Et puis héritez et passer outre ce que vous voulez comme ceci:

class OwnedModel(NamedModel): 
    class Meta(BaseNamedModelMeta): 
     verbose_name = 'owned object' 
Questions connexes