2014-07-22 10 views
9

Dire che ho un modello come questo.Come funziona l'accesso con chiave esterna Django

class Job(models.Model): 
    client = models.ForeignKey(Contacts, null=True) 

e permette di dire che ho lavoro j. So che posso accedere al client appartenenti a j come questo

j.client 

ma c'è anche

j.client_id 

Quindi la mia domanda è come si fa accedendo lavoro j.client?

Does django store client__id quindi quando viene chiamato j.client esegue una query per trovare l'oggetto corretto?

Oppure il riferimento oggetto memorizzato in j e l'accesso a client__id sta ottenendo l'ID dall'oggetto Contatto?

Ho guardato tutto il codice sorgente un po ', ma non riusciva a trovare la risposta alla mia domanda

+0

possibile duplicato di [Quando Django cerca la chiave primaria delle chiavi esterne?] (Http://stackoverflow.com/questions/13631211/when-does-django-look-up-the-primary-key-of -foreign-keys) –

risposta

8

questo è spiegato nella documentazione:
https://docs.djangoproject.com/en/dev/ref/models/fields/#database-representation

Nel database c'è solo client_id campo (singolo trattino basso)

Sull'istanza del modello si avrà l'attributo client, quando ci si accederà in questo modo, Django caricherà l'oggetto correlato dal db e l'istanza come un'altra istanza del modello.

Si avrà anche l'attributo client_id (un carattere di sottolineatura) che ha il valore della chiave primaria dell'oggetto correlato, come memorizzato nel campo db.

Nel fare query ORM si sono in grado di utilizzare la sintassi client__id (doppia sottolineatura) per ricerca contro i campi del modello relativo, ad esempio, si potrebbe anche fare client__name se Client modello aveva un campo name. Questo diventerà una query SQL JOIN su entrambi i modelli.

esempio

Job.objects.get(client__id=1) 
Job.objects.filter(client__name='John') 

client = Client.objects.get(pk=1) 
Job.objects.get(client=client) 
+0

Sì, ho notato il mio errore e ho modificato la domanda per riflettere correttamente l'accesso. Fantastica questa è la conferma che stavo cercando. Sospettavo che fosse così, grazie amico! –

2

j.client ti dà l'oggetto models.Model. È possibile accedere le sue proprietà come ...

client = j.client 

id = client.id 
name = client.name 

Ma non ci dovrebbe essere un campo j.client__id. È necessario utilizzare j.client.id per ottenere il campo id. Sebbene sia possibile utilizzare il campo j.client__id per fare filtri e così via.

Quindi,

id = j.client.id # good 
id = j.client__id # bad 

e

job = Job.objects.get(client__id=1) # good 
job = Job.objects.get(client.id=1) # bad 
+0

dispiace non volevo mettere l'extra _ C'è un campo client_id provatelo –

+0

Dalla documentazione di Django - "Dietro le quinte, Django aggiunge '_id' al nome del campo per creare il proprio database nome della colonna. ". –

+0

E non sono sicuro del motivo per cui qualcuno avrebbe -1 la mia risposta basata su una domanda errata. –

9

Che cosa si sta parlando, probabilmente è client e client_id (singola sottolineatura).

L'attributo client_id è un attributo regolare (numero intero). Questa è la chiave esterna che viene salvata nel database.Si vedrà sempre una colonna client_id nel database, anche se si specifica ForeignKey come client.

L'attributo client è un'istanza del descrittore di oggetto. È una classe speciale che sovrascrive i metodi __get__ e __set__, quindi le impostazioni e l'accesso a tali attributi invoca i metodi di quella classe. Questa è la magia che ti dà accesso all'istanza reale del modello correlato. __get__ recupererà l'istanza del modello corretta dal database se non è già stata caricata, in base all'attributo client_id. __set__ imposterà anche l'attributo client_id alla chiave primaria dell'oggetto correlato, in modo che client_id sia sempre aggiornato.

Si noti che questo attributo è disponibile anche nelle ricerche di query ed è molto utile. Ad esempio, se avete solo la chiave primaria di un corpo estraneo, e non il modello di istanza stessa, le seguenti query molto simile:

job = Job.objects.filter(client__id=pk) 
job = Job.objects.filter(client_id=pk) 

Tuttavia, sotto la prima query accede a un attributo sull'oggetto correlato (doppia sottolineatura) ed esegue un OUTER JOIN. La seconda query accede sempre ad un attributo locale, quindi non è necessario eseguire la dichiarazione OUTER JOIN e il rendimento di salvataggio.

+0

Sì, ho già cambiato la mia domanda, ho notato l'errore un minuto dopo averlo pubblicato. Voi ragazzi siete troppo veloci per me>.

Problemi correlati