Jak poprawnie używać wyszukiwania wstecznego FK w Django, aby wyświetlać instancje modelu potomnego w CBV

Nov 28 2020

Mam dwa modele, jeden z nich wskazuje na drugi jak pokazano poniżej:

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", ...)

Staram się zebrać wszystkie Firmy , które zostały stworzone dla danej Grupy . Więc próbuję uzyskać company_id(i inne) wartości w Djnago UpdateViewjako listę w szablonie. Mój CBV jest taki, jak pokazano:

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.

Czy ktoś mógłby mi dać znać, jak to działa?

Aktualizacja

Jak wyjaśniono (@Mahmoud Adel), zmodyfikowałem mój, UpdateViewjak pokazano poniżej:

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'])

A potem w szablonie robię:

{{ group.related_grp_company }}

Dzięki temu otrzymuję wynik <app>.Company.None.

Odpowiedzi

MahmoudAdel Nov 29 2020 at 07:39

AKTUALIZACJA: Po przetestowaniu na moim lokalnym środowisku env w celu rozwiązania problemów zgłoszonych w komentarzach, to jest ostateczna odpowiedź

Powinieneś zastąpić 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

Zauważ, że kolejność ma znaczenie tutaj w powyższym zapytaniu, zrobienie tego prefetch_relatedprzed getnaprawi błąd dla 'Group' object has no attribute 'prefetch_related'.

Możesz również zrezygnować z użycia prefetch_relatedi zrobić tylko getz powyższego zapytania, a to również zadziała, ale prefetch_relatedsugeruje się użycie w celu optymalizacji wydajności, ponieważ za każdym razem będziesz pobierać powiązane firmy

Następnie templatemożesz po prostu zadzwonić related_grp_company.allz obiektu, powiedzmy, że przekazujesz bieżący Groupobiekt jako groupszablon, więc powinno być group.related_grp_company.all, to jest QuerySetlista, więc zapętl ją lub zrób, co chcesz.

na przykład:

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

Ponieważ nie alldodaliśmy, że otrzymujemy <app>.Company.Nonewcześniej

Wskazówka:

related_namejest używany do odwrotnej relacji , sugerowałbym zmianę jego nazwy na companiestak, aby była jaśniejsza, na przykład:

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

więc użycie go później będzie jak group.companies()