12

如何使用 django QuerySet API 创建跨 M2M 关系芯片的完全外部联接的查询?

它不受支持,欢迎提出一些关于创建我自己的经理来执行此操作的提示。

编辑添加: @S.Lott:感谢您的启发。对 OUTER JOIN 的需求来自应用程序。它必须生成一个显示输入数据的报告,即使它仍然不完整。我不知道结果将是一个新的类/模型。你的提示会对我有很大帮助。

4

2 回答 2

17

Django 不支持通常 SQL 意义上的“连接”——它支持对象导航。

请注意,关系连接(内部或外部)创建了一个新的实体“类”。一个在 Django 中没有定义的。所以没有适当的“结果集”,因为你返回的东西没有类定义。您可以做的最好的事情是定义一个元组,它将与 None 一起用于缺少的组合。

左(或右)外连接看起来像这样。它创建了两个不相交的子集,一个有一组相关实体,另一个没有。

for obj in Model1.objects.all():
    if obj.model2_set().count() == 0:
        # process (obj, None) -- no Model2 association
    else:
        for obj2 in obj.model2_set.all():
            # process (obj, obj2) -- the "inner join" result

“完整”外部联接是没有关系的剩余项目的联合。

for obj2 in Model2.objects.all():
    if obj2.model1_set().count() == 0:
        # process (None, obj2) -- no Model1 association

问题始终是,你对这个由三个不同对象子集组成的奇怪集合做了什么处理?

对象数据库的重点是将处理集中在对象及其关联对象上。

称为“关系连接”的特殊集合从未出现在原始对象模型中。它是由两个(或更多)原始对象构建的一类新对象。

更糟糕的是,外连接会创建一个包含多个子类(内连接、左外连接和右外连接)的集合。那一堆东西是什么意思

等等,情况可能会变得更糟。如果处理包括对缺失属性的检查(即if someObj.anObj2attribute is None:我们本质上是在寻找Model1没有Model2关联对象的项目。嗯......为什么我们将它们放在外部连接中,只是为了使用if语句过滤它们?为什么不直接做单独的查询和正确处理每个子集?


Edit: When you're showing "incomplete" status, it isn't an outer-join at all. It's much simpler. You need to create one (or two) separate collections in your view function for your template to display.

First, you should use status codes, not the presence or absence of a foreign key. Optional foreign keys don't have "reasons" -- they're either there or not there. A status code can provide useful shades of meaning ("incomplete", "in error", "broken", "not applicable", "to be deleted", etc.)

errorList1 = Model1.objects.filter( status="Incomplete" )
errorList2 = Model2.objects.filter( status="Incomplete" )

These two are the two non-join parts of a full outer join. You can then display these two error lists in your template with appropriate column titles and status codes and everything.

You can even put them into a single table to mimic the old full outer join report people used to see

<table>
    <tr><th>Model1</th><th>Model2</th></tr>
    {% for e1 in errorList1 %}
    <tr><td>e1</td><td>NULL</td></tr>
    {% endfor %}
    {% for e2 in errorList2 %}
    <tr><td>NULL</td><td>e2</td></tr>
    {% endfor %}
</table>

Looks like a full outer join report. Without the full outer join.

于 2008-10-31T10:23:19.783 回答
1

Colin, one of the guys I work with, wrote a post awhile back about doing custom joins in Django:

http://www.caktusgroup.com/blog/2009/09/28/custom-joins-with-djangos-queryjoin/

You might be able to find something useful there!

于 2010-03-12T01:14:01.783 回答