2012-04-27 13 views
13

È possibile ottenere il modello correlato di una chiave esterna attraverso il campo della chiave esterna stesso?Django Foreign Key: ottieni un modello correlato?

Per esempio, se ho 3 modelli:

class ModelA(models.Model) 
    field1 = models.CharField(max_length=10) 

class ModelB(models.Model) 
    field1 = models.CharField(max_length=10) 

class ModelC(models.Model) 
    field1 = models.CharField(max_length=10) 
    field2 = models.ForeignKey(ModelA) 
    field3 = models.ForeignKey(ModelB) 

e voglio fare:

for field in ModelC._meta.fields: 
    if field.get_internal_type() == "ForeignKey": 
     #get the related model for field e.g. ModelA or ModelB 

Questo è possibile utilizzando solo i modelli stessi, piuttosto che le istanze dei modelli?

risposta

19

Se ModelA ha un campo FK chiamato "foo", allora questo è come è possibile ottenere il modello correlate:

ModelA._meta.get_field('foo').rel.to 

con il tuo codice, sarebbe assomigliare:

for field in ModelC._meta.fields: 
    if field.get_internal_type() == "ForeignKey": 
     print field.rel.to 

Se trovato fuori usando il completamento di tabulazione nella shell molto tempo fa, funziona ancora. Potresti voler imparare a usare la shell per decodificare cose del genere.

+0

Aggiornamento: nel nuovo rilascio di Django 2.0, sembra che "rel" non sia più un campo di ForeignKey. Potresti provare: 'ModelA._meta.get_field ('foo'). Related_model'. Lo capisco digitando "tab" per completare automaticamente nella riga di comando. –

0

Quando si tenta di estrarre relazioni come questa, utilizzo molte sperimentazioni da riga di comando. Un modello comune che uso è _=starting_point.<chained_attributes>;pprint((_, dir(_))). Per esempio:

_=ModelC;pprint((_, dir(_))) 
_=ModelC.field2;pprint((_, dir(_))) 
_=ModelC.field2.field;pprint((_, dir(_))) 
_=ModelC.field2.field.rel;pprint((_, dir(_))) 
_=ModelC.field2.field.rel.to;pprint((_, dir(_))) 

(Avrai bisogno di fare from pprint import pprint prima, naturalmente.) Che mi permette di sperimentare con l'aggiunta/rimozione di attributi fino a trovare la voce che voglio ... mentre vedere chiaramente quello che ho e cosa è disponibile al livello successivo. Da questo, ottengo ModelC.field2.field.rel.to == ModelA. Lo stesso modello base può essere utilizzato per esplorare relazioni inverse, relazioni molti-a-molti, iniziando con un'istanza piuttosto che con la classe, ecc.

Problemi correlati