Django: Setel kunci asing menggunakan integer?

104

Apakah ada cara untuk menyetel hubungan kunci asing menggunakan id integer model? Ini untuk tujuan pengoptimalan.

Misalnya, saya memiliki model Karyawan:

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

dan

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

Saya ingin fleksibilitas memiliki jenis karyawan yang tidak terbatas, tetapi dalam aplikasi yang diterapkan kemungkinan hanya akan ada satu jenis jadi saya bertanya-tanya apakah ada cara untuk melakukan hardcode id dan mengatur hubungan dengan cara ini. Dengan cara ini saya dapat menghindari panggilan db untuk mendapatkan objek EmployeeType terlebih dahulu.

Pengguna
sumber

Jawaban:

206

Ya:

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

ForeignKeybidang menyimpan nilainya dalam atribut dengan _iddi bagian akhir, yang dapat Anda akses langsung untuk menghindari mengunjungi database.

The _idversi dari ForeignKeyadalah aspek yang sangat berguna dari Django, yang setiap orang harus tahu dan menggunakan dari waktu ke waktu jika diperlukan.

peringatan:

@RuneKaagaard menunjukkan bahwa employee.typetidak akurat setelah itu dalam versi Django terkini, bahkan setelah memanggil employee.save()(ini memegang nilai lamanya). Menggunakannya tentu saja akan menggagalkan tujuan pengoptimalan di atas, tetapi saya lebih suka kueri tambahan yang tidak disengaja menjadi tidak benar. Jadi berhati-hatilah, hanya gunakan ini setelah Anda selesai mengerjakan instance Anda (misalnya employee).

Will Hardy
sumber
10
Apakah ini didokumentasikan?
Scott Stafford
8
Menggunakan nilai kunci asing secara langsung: docs.djangoproject.com/en/1.8/topics/db/optimization/…
Dan Oliphant
1
Saya menguji ini pada Django 1.7 hari ini, dan itu bukan ide yang bagus di sana. Saat berfungsi, dan typebidang ditulis ke database, jika Anda mengakses typeproperti setelahnya, itu tidak mencerminkan perubahan. Dikatakan dalam kode, ini akan gagal assert(employe.type.id == 4).
Rune Kaagaard
3
@AmichaiSchreiber Saya yakin terbitan Django berikutnya akan memiliki perbaikan untuk masalah ini: code.djangoproject.com/ticket/27710
Will Hardy
2
Untuk siapa pun yang datang ke sini di masa mendatang, masalah ini diperbaiki di Django 2.1 .
humcat
45

Alternatif yang menggunakan create untuk membuat objek dan menyimpannya ke database dalam satu baris:

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