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.

Пользователь
источник

Ответы:

206

Ага:

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
Прямое
Дэн Олифант,
1
Сегодня я тестировал это на Django 1.7, и там это не очень хорошая идея. Хотя он работает и typeполе записывается в базу данных, если вы typeвпоследствии получите доступ к свойству, оно не отражает изменения. В коде сказано, что это не удастся assert(employe.type.id == 4).
Руне Каагаард
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)
Джасинда
источник