2017-03-23 1 views
0

J'ai 2 modèles. Personnages et personnagesDétails d'un site django avec lequel je plaisante.La requête Django select_related ne retourne pas toutes les valeurs au modèle

CharactersDetails a une relation foreignkey aux personnages

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

À mon avis, je fais ceci:

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

Dans mon modèle, je ne revenir les champs des CharactersDetails table.

Dans le shell manage.py, j'ai exécuté la même requête et trouvé que les champs CharactersDetails et Characters étaient retournés (ce que je veux), mais lorsque la vue obtient l'objet context, elle n'affiche que les éléments à partir de la table 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 
>>> 

Je prends cette même requête et le coller dans le 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 

Et je reçois tous les champs. Mais le modèle ne passe pas les 6 dernières valeurs. Je pouvais voir quand j'ajouter un .values ​​() à la fin de la queryset puis faire:

{{ character_info }} 

dans le modèle que je vois:

<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}]> 

Ai-je fait quelque chose de mal ou est il y a une façon particulière que je devrais appeler ces valeurs du modèle?

Merci d'avoir lu.

Répondre

0

Faire select_related('character_link') ne pas ajouter les attributs à l'instance character_info, il récupère juste le character_info du db en même temps que character_link, en utilisant une jointure interne.

Dans le modèle, vous accédez à l'instance character_link{{ character_info.character_link }}.

Si vous utilisez values(), vous devez inclure explicitement les champs de character_link:

.values('field1', 'field2', 'character_link__field', ...) 
0

La méthode queryset .values() ne pas ajouter les attributs de manière implicite les clés étrangères sélectionnées. Voici un extract of the documentation:

Quelques subtilités qui méritent d'être mentionnées:

  • Si vous avez un champ appelé foo qui est un ForeignKey, la valeur par défaut values() appel renverra une clé de dictionnaire appelé foo_id, puisqu'il s'agit du nom de l'attribut de modèle masqué qui stocke la valeur réelle (l'attribut foo fait référence au modèle associé). Lorsque vous appelez le values() et que vous passez des noms de champs, vous pouvez passer dans foo ou foo_id et vous obtiendrez la même chose (la clé du dictionnaire correspondra au nom du champ que vous avez transmis).

Vous devez lister les champs comme arguments values('character_link__field1', 'character_link__field2'...) ... ou tout simplement ne pas l'utiliser et les objets ORM de processus, qui utilisera les données récupérées dans une requête.

Avec des outils tels que django-debug-toolbar, vous pouvez inspecter vos demandes pour vous assurer qu'une seule requête SQL est effectuée lors du rendu de votre modèle.