Django: Встановити зовнішній ключ за допомогою цілого числа?


104

Чи є спосіб встановити зв'язок із зовнішнім ключем, використовуючи цілий ідентифікатор моделі? Це було б з метою оптимізації.

Наприклад, припустимо, що у мене є модель «Співробітник»:

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

і

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

Я хочу гнучкості мати необмежену кількість співробітників, але у розгорнутому додатку, ймовірно, буде лише один тип, тому мені цікаво, чи є спосіб жорсткого коду ідентифікатора та встановлення відносин таким чином. Таким чином я можу уникнути db-дзвінка, щоб спочатку отримати об’єкт EmployeeType.

Відповіді:


205

Так:

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

ForeignKeyполя зберігають своє значення в атрибуті, _idв кінці якого ви можете отримати доступ безпосередньо, щоб уникнути відвідування бази даних.

_idВерсія ForeignKeyє особливо корисним аспектом Django, один , що кожен повинен знати і використовувати час від часу , коли це необхідно.

застереження:

@RuneKaagaard вказує, що employee.typeзгодом це не є точним у останніх версіях Django, навіть після виклику employee.save()(він має своє старе значення). Використання його, звичайно, переможе мету вищеописаної оптимізації, але я вважаю за краще, щоб випадковий додатковий запит був невірним. Тому будьте обережні, використовуйте це лише тоді, коли ви закінчите роботу над своїм примірником (наприклад employee).


10
Це документально підтверджено?
— Скотт Стаффорд

8
Безпосереднє використання зовнішніх ключових значень: docs.djangoproject.com/en/1.8/topics/db/optimization/…
— Dan Oliphant

1
Я протестував це сьогодні на Django 1.7, і це не дуже добре. Поки воно працює, і typeполе записується в базу даних, якщо ви звертаєтесь до typeресурсу після цього, воно не відображає зміни. Сказаний у коді, це не вдасться assert(employe.type.id == 4).
— Rune Kaagaard

3
@AmichaiSchreiber Я вважаю, що наступний реліз Django матиме виправлення цієї проблеми: code.djangoproject.com/ticket/27710
— Will Hardy

2
Для тих, хто прийде сюди в майбутньому, ця проблема виправлена ​​в Django 2.1 .
— humcat

45

Альтернатива, яка використовує create, щоб створити об'єкт і зберегти його в базі даних в одному рядку:

employee = Employee.objects.create(first_name='first', last_name='last', type_id=4)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.