2009-09-01 3 views
6

Vorrei utilizzare le proprietà della classe Meta di un modello ereditario per configurare un campo definito in un modello astratto più in alto dell'albero di eredità:Impossibile utilizzare una classe Meta del modello Django ereditario per configurare un campo definito in un modello astratto ereditato

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' 

Vorrei che il testo di aiuto sul campo del nome di forme OwnedModel a dire 'un nome significativo per questo oggetto di proprietà'. Ma non è: manca la parola 'owned', che suggerirebbe che il verbose_name di NamedModel.Meta venga usato quando il modello è impostato, non OwnedModel.Meta.

Questo non è esattamente ciò che mi aspetto da un punto di vista dell'ereditarietà: c'è un modo per ottenere il campo da creare in base al quale Meta.verbose_name fa riferimento al valore sulla classe del modello non astratto, non a quella astratta su quale il campo è stato definito?

Oppure sono un idiota?

(questo può sembrare un esempio banale, ed è: ma è solo per illustrare il punto di qualcosa di più importante e complesso che sto cercando di fare)

Molte grazie in anticipo.

risposta

1

Penso che ciò accada perché Meta.verbose_name viene utilizzato e NamedModel.name viene creato quando viene analizzata la classe NamedModel. Quindi più tardi, quando classe OwnedModel viene analizzato, non c'è alcuna possibilità di cambiare nulla.

Forse è possibile impostare la proprietà help_text su OwnedModel.name in seguito, ma questo potrebbe cambiare anche NamedModel.name.

In situazioni simili ho messo le parti variabili nell'attributo di classe del modello (non in Meta) e poi ho usato i metodi/proprietà di run time per generare i testi che mi servono.

+0

Sì, io credo che sia così. Dopo aver seguito il flusso, sono più chiaro sul ciclo di vita: i campi vengono valutati quando la classe viene analizzata, quindi l'eredità non viene considerata. E ho provato gli attributi di classe al di fuori della meta ... lo stesso problema, naturalmente. Sono felice di scavalcare le classi di campi e potrei usare quello (+ quello che suggerisci) per ottenere l'effetto desiderato. –

1

Infatti ho finito col fare quanto segue. Il modello base viene fornito con un metodo di classe dynamic_field_definition(), che può essere usato per correggere i campi, con l'argomento cls come classe corretta (ereditaria). Ciò significa che gli attributi Meta di quel cls sono di quel bambino corretto, non della base originale.

Quindi collego questo metodo per ricevere il segnale class_prepared, in modo da sapere che tutto è pronto altrimenti.

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) 

Poi le proprietà di campo che variano con classe del modello sono semplicemente riconfigurati da tale metodo di classe (o più probabilmente il metodo override nelle classi derivate).

È un modo leggermente hacky per portare un ultimo po 'di OO-ness ai modelli Django, ma funziona perfettamente per il mio scopo.

2

Perché non provi a fare un corso.

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

E poi ereditare e ignorare quello che vuoi in questo modo:

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