Como usar corretamente a pesquisa FK reversa do Django para mostrar instâncias do modelo filho em CBV

Nov 28 2020

Tenho dois modelos, campo de um deles apontando para o outro conforme mostrado abaixo:

class Group(models.Model):
    group_company_id = models.CharField(primary_key=True, ...)
    
class Company(models.Model):
    company_id = models.CharField(primary_key=True, ...)
    group_company = models.ForeignKey(Group, related_name="related_grp_company", ...)

Estou tentando obter todas as empresas que foram criadas para um determinado grupo . Portanto, estou tentando obter os company_id(e outros) valores em Djnago UpdateViewcomo uma lista no modelo. Meu CBV é como mostrado:

class GroupCompanyChangeView(UpdateView):
    template_name =  ...
    model = Group
    form_class = ...
    success_url = reverse_lazy('group_list')

    grp_coy_units = Group.objects.prefetch_related('related_grp_company') # I am trying to get the values of `company_id` in the template but nothing is displayed.

Alguém poderia me dizer como fazer isso funcionar?

Atualizar

Conforme explicado (@Mahmoud Adel), eu modifiquei meu UpdateViewconforme mostrado abaixo:

class GroupCompanyChangeView(UpdateView):
    template_name =  ...
    model = Group
    form_class = ...
    success_url = reverse_lazy('group_list')

    def get_object(self, *args, **kwargs):
        return Group.objects.get(pk=self.kwargs['pk'])

E então, no modelo, estou fazendo:

{{ group.related_grp_company }}

Com isso, estou obtendo uma saída de <app>.Company.None.

Respostas

MahmoudAdel Nov 29 2020 at 07:39

ATUALIZAÇÃO: Depois de testar em meu ambiente local para resolver os problemas relatados nos comentários, esta é a resposta final

Você deve substituir get_object()

def get_object(self, *args, **kwargs):
        try:
            return Group.objects.prefetch_related('related_grp_company').get(pk=self.kwargs['pk'])
        except:
            return None

Observe que o pedido é importante aqui na consulta acima, fazer o prefetch_relatedbefore getcorrige o erro para 'Group' object has no attribute 'prefetch_related'.

Além disso, você pode deixar de usar prefetch_relatede apenas fazer getda consulta acima e funcionará também, mas o uso prefetch_relatedé sugerido para otimizar o desempenho, pois você buscará as empresas relacionadas todas as vezes

Em seguida, templatevocê pode simplesmente chamar related_grp_company.alldo objeto, digamos que você está passando o Groupobjeto atual como grouppara o seu modelo, então deve gostar group.related_grp_company.all, esta é uma QuerySetlista, então faça um loop sobre ela ou faça o que quiser.

por ex:

{%for d in object.related_grp_company.all%}
<h1>{{ d.company_id }}</h1>
{% endfor %}

Porque não adicionar allestávamos recebendo <app>.Company.Nonemais cedo

Dica:

related_nameé usado para a relação reversa , sugiro renomeá-lo para companiesassim ficar mais claro, por ex:

group_company = models.ForeignKey(Group, related_name="companies", ...)

então usá-lo mais tarde será como group.companies()