Как правильно использовать обратный поиск FK в Django для отображения экземпляров дочерней модели в CBV

Nov 28 2020

У меня две модели, одна из которых указывает на другую, как показано ниже:

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

Я пытаюсь собрать все компании , созданные для конкретной группы . Итак, я пытаюсь получить company_id(и другие) значения в Djnago UpdateViewв виде списка в шаблоне. Мой CBV такой, как показано:

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.

Может кто-нибудь, дайте мне знать, как заставить это работать?

Обновить

Как объяснялось (@Mahmoud Adel), я изменил свой, UpdateViewкак показано ниже:

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

А затем в шаблоне я делаю:

{{ group.related_grp_company }}

При этом я получаю результат <app>.Company.None.

Ответы

MahmoudAdel Nov 29 2020 at 07:39

ОБНОВЛЕНИЕ: после тестирования на моем локальном env для решения проблем, о которых сообщалось в комментариях, это окончательный ответ.

Вы должны переопределить 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

Обратите внимание, что порядок здесь имеет значение в приведенном выше запросе, выполнение prefetch_relatedдо getисправления ошибки для 'Group' object has no attribute 'prefetch_related'.

Кроме того, вы можете отказаться от использования prefetch_relatedи делать только getиз приведенного выше запроса, и он тоже будет работать, но использование prefetch_relatedрекомендуется для оптимизации производительности, поскольку вы будете каждый раз запрашивать связанные компании

Затем templateвы можете просто позвонить related_grp_company.allиз объекта, скажем, вы передаете текущий Groupобъект как groupсвой шаблон, поэтому ему должно понравиться group.related_grp_company.all, это QuerySetсписок, поэтому перебирайте его или делайте все, что хотите.

например:

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

Потому что мы не добавили, allчто получали <app>.Company.Noneраньше

Наконечник:

related_nameиспользуется для обратного отношения , я бы предложил переименовать его, чтобы companiesбыло понятнее, например:

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

так что использовать его позже будет как group.companies()