У меня есть 2 модели. Персонажи и персонажи Детали с сайта django, с которым я дурачусь.

Детали персонажа имеют отношение внешнего ключа к Персонажу

class CharactersDetails(models.Model):
    character_link = models.ForeignKey(Characters)

На мой взгляд, я делаю это:

'character_info': CharactersDetails.objects.select_related('character_link').filter(character_link_id=pk)

В моем шаблоне я получаю только поля из таблицы «Сведения о персонаже».

В оболочке manage.py я выполнил тот же запрос и обнаружил, что он на самом деле возвращает поля из CharactersDetails и Characters (что мне и нужно), но когда представление получает объект контекста, оно отображает только элементы из таблицы CharactersDetails. ,

(looking_for_guild_env)klainn:~/workspace (master) $ python manage.py shell
Python 3.4.3 (default, Nov 17 2016, 01:08:31) 
>>> from players.models import Characters,CharactersDetails
>>> myjunk = CharactersDetails.objects.select_related('character_link').filter(character_link_id=1)
>>> print(myjunk)
<QuerySet [<CharactersDetails: CharactersDetails object>]>
>>> print(myjunk.query)
SELECT "characters_details"."id", "characters_details"."character_link_id", "characters_details"."character_class_id", "characters_details"."character_race_id", "characters_details"."character_level", "characters_details"."character_armory_url", "characters_details"."character_profile_image_url", "characters_details"."character_profile_avatar_url", "characters_details"."character_profile_inset_url", "characters"."id", "characters"."character_owner_id", "characters"."character_name", "characters"."character_realm_id", "characters"."character_faction_id", "characters"."insert_date" FROM "characters_details" INNER JOIN "characters" ON ("characters_details"."character_link_id" = "characters"."id") WHERE "characters_details"."character_link_id" = 1
>>> 

Я беру тот же запрос и вставляю его в dbshell manage.py:

(looking_for_guild_env)klainn:~/workspace (master) $ python manage.py dbshell
sqlite> SELECT "characters_details"."id", "characters_details"."character_link_id", "characters_details"."character_class_id", "characters_details"."character_race_id", "characters_details"."character_level", "characters_details"."character_armory_url", "characters_details"."character_profile_image_url", "characters_details"."character_profile_avatar_url", "characters_details"."character_profile_inset_url", "characters"."id", "characters"."character_owner_id", "characters"."character_name", "characters"."character_realm_id", "characters"."character_faction_id", "characters"."insert_date" FROM "characters_details" INNER JOIN "characters" ON ("characters_details"."character_link_id" = "characters"."id") WHERE "characters_details"."character_link_id" = 1;
1|1|15|7|110|http://us.battle.net/wow/en/character/Stormrage/Peppiwyn/simple|stormrage/219/182881755-profilemain.jpg|stormrage/219/182881755-avatar.jpg|stormrage/219/182881755-inset.jpg|1|3|Peppiwyn|192|0|2017-03-20

И я получаю все поля. Но шаблон не получает последние 6 значений. Я мог видеть это, когда я добавляю .values () в конец набора запросов и затем делаю:

{{ character_info }}

В шаблоне я вижу:

<QuerySet [{'id': 1, 'character_profile_image_url': 'stormrage/219/182881755-profilemain.jpg', 'character_race_id': 7, 'character_level': 110, 'character_profile_avatar_url': 'stormrage/219/182881755-avatar.jpg', 'character_profile_inset_url': 'stormrage/219/182881755-inset.jpg', 'character_armory_url': 'http://us.battle.net/wow/en/character/Stormrage/Peppiwyn/simple', 'character_link_id': 1, 'character_class_id': 15}]>

Я сделал что-то не так или есть особый способ вызова этих значений из шаблона?

Спасибо за чтение.

1
JasonS 23 Мар 2017 в 18:29

2 ответа

Лучший ответ

Метод queryset .values() не добавляет неявно атрибуты выбранных внешних ключей. Вот выдержка из документация:

Несколько тонкостей, о которых стоит упомянуть:

  • Если у вас есть поле с именем foo, которое является ForeignKey, вызов по умолчанию values() вернет ключ словаря с именем foo_id, поскольку это имя скрытого атрибута модели, в котором хранится фактическое значение. (атрибут foo ссылается на связанную модель). Когда вы вызываете values() и передаете имена полей, вы можете передать либо foo, либо foo_id, и вы получите то же самое (ключ словаря будет соответствовать имени поля, в котором вы были переданы).

Вам нужно перечислить поля как values('character_link__field1', 'character_link__field2'...) аргументы ... или просто не использовать их и обрабатывать объекты ORM, которые будут использовать данные, полученные в одном запросе.

С помощью таких инструментов, как django-debug-toolbar, вы можете проверить свои запросы, чтобы убедиться, что только один SQL-запрос выполняется при рендеринге вашего шаблона.

1
Maxime Lorant 23 Мар 2017 в 15:42

Выполнение select_related('character_link') не добавляет атрибуты к экземпляру character_info, оно просто извлекает character_info из БД в то же время, что и character_link, используя внутреннее соединение.

В шаблоне вы получаете доступ к character_link экземпляру {{ character_info.character_link }}.

Если вы используете values(), вы должны явно включить поля из character_link:

.values('field1', 'field2', 'character_link__field', ...)
0
Alasdair 23 Мар 2017 в 15:40