Django: impostare la chiave esterna utilizzando il numero intero?


104

C'è un modo per impostare la relazione di chiave esterna utilizzando l'id intero di un modello? Questo sarebbe per scopi di ottimizzazione.

Ad esempio, supponiamo di avere un modello Employee:

class Employee(models.Model):
  first_name = models.CharField(max_length=100)
  last_name = models.CharField(max_length=100)
  type = models.ForeignKey('EmployeeType')

e

EmployeeType(models.Model):
  type = models.CharField(max_length=100)

Voglio la flessibilità di avere un numero illimitato di dipendenti, ma nell'applicazione distribuita ci sarà probabilmente un solo tipo, quindi mi chiedo se esiste un modo per codificare l'ID e impostare la relazione in questo modo. In questo modo posso evitare una chiamata db per ottenere prima l'oggetto EmployeeType.

Risposte:


206

Sì:

employee = Employee(first_name="Name", last_name="Name")
employee.type_id = 4
employee.save()

ForeignKeyi campi memorizzano il loro valore in un attributo con _idalla fine, a cui puoi accedere direttamente per evitare di visitare il database.

La _idversione di a ForeignKeyè un aspetto particolarmente utile di Django, che tutti dovrebbero conoscere e utilizzare di volta in volta quando appropriato.

avvertimento:

@RuneKaagaard sottolinea che employee.typenon è accurato in seguito nelle recenti versioni di Django, anche dopo la chiamata employee.save()(mantiene il suo vecchio valore). Il suo utilizzo vanificherebbe ovviamente lo scopo dell'ottimizzazione di cui sopra, ma preferirei che una query extra accidentale non fosse corretta. Quindi fai attenzione, usalo solo quando hai finito di lavorare sulla tua istanza (ad esempio employee).


10
È documentato?
Scott Stafford

8
Utilizzo diretto dei valori delle chiavi esterne: docs.djangoproject.com/en/1.8/topics/db/optimization/…
Dan Oliphant,

1
L'ho testato su Django 1.7 oggi e non è una buona idea lì. Mentre funziona e il typecampo viene scritto nel database, se accedi alla typeproprietà in seguito, non riflette la modifica. Detto in codice, questo fallirebbe assert(employe.type.id == 4).
Rune Kaagaard

3
@AmichaiSchreiber Credo che la prossima versione di Django avrà una soluzione per questo problema: code.djangoproject.com/ticket/27710
Will Hardy

2
Per chiunque venga qui in futuro, questo problema è stato risolto in Django 2.1 .
humcat

45

Un'alternativa che utilizza create per creare l'oggetto e salvarlo nel database in una riga:

employee = Employee.objects.create(first_name='first', last_name='last', type_id=4)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.