Есть ли какая-либо разница между использованием в файле ORM Django просто `foreign_key =` vs `foreign_key_id =`? - PullRequest
0 голосов
/ 10 ноября 2018

Похоже, что нет разницы между следующим:

ModelA.objects.filter(modelb_id=a_model_id)
ModelA.objects.filter(modelb=a_model_id)

Распечатка SQL, который Django генерирует для обоих случаев, показывает, что он одинаков. Однако я нигде не смог найти это официально документированное, и поэтому я обеспокоен тем, что может быть случай, когда использование только modelb может привести к чему-то отличному от modelb_id.

Мне особенно интересно, когда кто-то указывает мне на официальный источник, который подтверждает, что эти вещи эквивалентны.

1 Ответ

0 голосов
/ 10 ноября 2018

TLDR: Лучше учесть рекомендации авторов каркаса и использовать имена полей модели.

Представление базы данных

За кулисами Django добавляет «_id» к имени поля, чтобы создать его имя столбца базы данных. В приведенном выше примере таблица базы данных для модели автомобиля будет иметь столбец factory_id. (Вы можете изменить это явно, указав db_column). Однако ваш код никогда не должен иметь дело с именем столбца базы данных, если вы не пишете пользовательский SQL. Вы всегда будете иметь дело с именами полей вашего модельного объекта. Ссылка

Подкласс моделей полей django.db.models.fields.Field. Класс Field имеет поле attname, которое задокументировано внутри исходного кода как способ разрешения атрибута для использования в объекте модели.

# A guide to Field parameters:
#
#   * name:      The name of the field specified in the model.
#   * attname:   The attribute to use on the model object. This is the same as
#                "name", except in the case of ForeignKeys, where "_id" is
#                appended.
#   * db_column: The db_column specified in the model (or None).
#   * column:    The database column for this field. This is the same as
#                "attname", except if db_column is specified.
#
# Code that introspects values, or does other dynamic things, should use
# attname. For example, this gets the primary key value of object "obj":
#
#     getattr(obj, opts.pk.attname)

Как часть потока выполнения к преобразованию имен QuerySet.filter в kwargs для скомпилированного запроса SQL , имена преобразуются в кортежи PathInfo, содержащие поля модели для соответствующих имен.

В строке 1354 для django.db.models.sql.query.Query есть следующая строка:

field = opts.get_field(name)

Теперь opts является экземпляром django.db.models.options.Options, а метод get_field делегирует кешированные свойства _forward_fields_map или fields_map.

Когда вы посмотрите на реализацию этих двух свойств, вы увидите, что они возвращают словарь, отображающий field.name в field вместе с field.attname в field.

Таким образом, modelb_id или modelb разрешается в поле модели из любого из кэшированных свойств.

На мой взгляд, не имеет значения, что modelb_id или modelb передается в качестве ключевого аргумента QuerySet.filter. Только для того, чтобы первое ключевое слово требовало знания деталей реализации.

Однако лучше учесть рекомендации авторов каркаса и использовать имена полей модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...