Django: Fremdschlüssel mit Ganzzahl setzen?

104

Gibt es eine Möglichkeit, die Fremdschlüsselbeziehung mithilfe der Ganzzahl-ID eines Modells festzulegen? Dies wäre zu Optimierungszwecken.

Angenommen, ich habe ein Mitarbeitermodell:

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

und

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

Ich möchte die Flexibilität, unbegrenzte Mitarbeitertypen zu haben, aber in der bereitgestellten Anwendung wird es wahrscheinlich nur einen einzigen Typ geben. Daher frage ich mich, ob es eine Möglichkeit gibt, die ID fest zu codieren und die Beziehung auf diese Weise festzulegen. Auf diese Weise kann ich einen Datenbankaufruf vermeiden, um zuerst das EmployeeType-Objekt abzurufen.

Benutzer
quelle

Antworten:

205

Ja:

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

ForeignKey Felder speichern ihren Wert in einem Attribut mit _id am Ende, auf das Sie direkt zugreifen können, um einen Besuch der Datenbank zu vermeiden.

Die _idVersion von a ForeignKeyist ein besonders nützlicher Aspekt von Django, den jeder kennen und bei Bedarf von Zeit zu Zeit verwenden sollte.

Vorbehalt:

@RuneKaagaard weist darauf hin, dass dies employee.typein den letzten Django-Versionen auch nach dem Aufruf nicht mehr korrekt ist employee.save()(es behält seinen alten Wert). Die Verwendung würde natürlich den Zweck der obigen Optimierung zunichte machen, aber ich würde es vorziehen, wenn eine versehentliche zusätzliche Abfrage falsch wäre. Seien Sie also vorsichtig, verwenden Sie diese Option nur, wenn Sie mit der Arbeit an Ihrer Instanz fertig sind (z employee. B. ).

Will Hardy
quelle
10
Ist das dokumentiert?
Scott Stafford
8
Fremdschlüsselwerte direkt verwenden: docs.djangoproject.com/de/1.8/topics/db/optimization/…
Dan Oliphant
1
Ich habe dies heute auf Django 1.7 getestet und es ist dort keine gute Idee. Während es funktioniert und das typeFeld in die Datenbank geschrieben wird, typespiegelt es die Änderung nicht wider , wenn Sie anschließend auf die Eigenschaft zugreifen . Im Code gesagt, würde dies fehlschlagen assert(employe.type.id == 4).
Rune Kaagaard
3
@ AmichaiSchreiber Ich glaube, die nächste Version von Django wird eine Lösung für dieses Problem haben: code.djangoproject.com/ticket/27710
Will Hardy
2
Für alle, die in Zukunft hierher kommen, ist dieses Problem in Django 2.1 behoben .
Humcat
45

Eine Alternative, bei der create verwendet wird , um das Objekt zu erstellen und in einer Zeile in der Datenbank zu speichern:

employee = Employee.objects.create(first_name='first', last_name='last', type_id=4)
Jacinda
quelle