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.