Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Django : Sérialiser le résultat d'un Queryset construit avec prefetch_related

+1 vote

Modèles:

class Agent(models.Model):
    ...
class AgentAddress(models.Model):
   agent = models.ForeignKey(Agent)
   ...

Vue:

class AgentDetailModal(LoginRequiredMixin, DetailView):
template_name = 'agent/agent_detail_modal.html'
model = Agent


def render_to_response(self, context, **response_kwargs):
    agent = Agent.objects.prefetch_related('agentaddress_set').filter(pk=self.kwargs['pk'])
    print agent
    agent_serialized = serializers.serialize('json', agent)
    print agent_serialized
    from django.db import connection
    print connection.queries
    return JsonResponse(agent_serialized, safe=False)

Le "print connection.queries" me renvoi bien deux requêtes dont une qui tape dans la table AgentAddress. Le "print agent" me renvoi bel object

[<Agent: Firstname Lastname>]

mais le "print agent_serialized" me renvoi un beau dictionnaire SANS aucune référence à ma chère table "AgentAddress".
(Je fais bien sûr le test avec un agent qui a une pk avec une entrée dans la table "AgentAddress").

Est-ce que le merge python fait par prefetch_related ne serait pas en cause ? Lié au fait que "print agent.query" ne renvoi qu'une seule requête ?

Je voudrais renvoyer tout ce que concerne un Agent et qui est stocké dans qques tables liées comme "AgentAdress"

( Et hors titre, je suis étonné que la DetailView ne filtre pas automatiquement par pk et que je doive rajouter un "filter".)

demandé 25-Jan-2015 par Youpsla (120 points)
edité 25-Jan-2015 par Youpsla

1 Réponse

+3 votes
 
Meilleure réponse

Je voudrais renvoyer tout ce que concerne un Agent et qui est stocké dans qques tables liées comme AgentAddress"

a = Agent.objects.select_related('agentaddress').get(pk=5)
ad = a.agentaddress_set.all() # aucune requete sur la db

Dans ce cas, il s'agit d'un simple foreign key, donc un select related fait l'affaire.

répondu 25-Jan-2015 par Nsukami_ (1,976 points)
sélectionné 26-Jan-2015 par Youpsla

Merci beaucoup. Cela fonctionne à merveille. J'ai trouvé une solution fonctionnelle (en 1.7) en faisant:

agent = Agent.objects.filter(pk=self.kwargs['pk']).prefetch_related(
            Prefetch('agentaddress_set', to_attr="dede"),
            Prefetch('agentvarious_set', to_attr="dodo"))

Pas encore tout compris à ce qui se passe en interne mais vais regarder.

Tu précise qu'il s'agit d'une FK donc selectrelated est OK. Cela sous-entend que prefetchrelated s'utilisera en m2m ?

@Youpsla grosso merdo, oui, prefetch related pour les relations de type m2m. Je te colle vite fait ce qu'il faut retenir: "prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related". Ça fait plaisir de parler français :)

...