如何正确使用 Django 反向 FK 查找在 CBV 中显示子模型的实例

Posted

技术标签:

【中文标题】如何正确使用 Django 反向 FK 查找在 CBV 中显示子模型的实例【英文标题】:How to correctly use Django reverse FK lookup to show instances of the child model in CBV 【发布时间】:2021-03-11 09:47:36 【问题描述】:

我有两个模型,其中一个的字段指向另一个,如下所示:

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

我正在尝试获取为特定 Group 创建的所有 Companies。因此,我试图将 Djnago UpdateView 中的 company_id (和其他)值作为模板中的列表。我的 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的输出。

【问题讨论】:

【参考方案1】:

更新:在我的本地环境上进行测试以解决 cmets 中报告的问题后,这是最终答案

你应该覆盖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

请注意,上述查询中的顺序很重要,在get 之前执行prefetch_related 可以修复'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,所以我们得到了&lt;app&gt;.Company.None

提示:

related_name 用于反向关系,我建议将其重命名为companies,这样会更清晰,例如:

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

所以以后使用它就像group.companies()

【讨论】:

感谢您的回答。我收到错误Company matching query does not exist. 我错过了什么吗?我已将覆盖放在** GroupCompanyChangeView** UpdateView 这可能是因为具有所请求id的公司不存在,您是否尝试使用get_object_or_404(),如答案所示? 实际上,正如我已经提出的问题,我正在尝试将所有 公司 纳入 Group。是的,集团下有公司。无论如何,使用get_object_or_404() 我收到错误'Company' object has no attribute 'prefetch_related' 对不起我的错,答案是获取与公司相关的所有组对象我已经更新了Group的答案 我很高兴您现在一切顺利!也谢谢你,祝你有美好的一天:)

以上是关于如何正确使用 Django 反向 FK 查找在 CBV 中显示子模型的实例的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM相关

Django级联删除反向外键

如何在 DJango 管理界面中显示 ForeignKey 反向查找列表?

Django:使用任意 URL 组件进行反向 URL 查找

Django 通过 ForeignKey 反向查找

在 Django 模板中过滤反向查找