回答

收藏

Django中的完全外部联接

技术问答 技术问答 312 人阅读 | 0 人回复 | 2023-09-14

如何使用django QuerySet API创建跨M2M关系芯片的完全外部联接的查询?' c5 ~( }) n$ i6 U/ J
它不受支持,欢迎提供有关创建我自己的经理来执行此操作的提示。' G7 c9 d6 ]+ ?( l" x7 b# E
编辑添加: @ S.Lott:感谢您的启发。应用程序需要使用OUTER% n( Q% }4 N( |2 [) d
JOIN。即使它仍然不完整,它也必须生成一个报告,显示输入的数据。我不知道结果将是一个新的类/模型。您的提示将对我有很大帮助。
( C. L6 ?0 s/ n2 j! r5 {               
, B& g  a( c1 `解决方案:8 {, b! {8 Y( U" p- `7 G$ c; ?
               
- t$ H) X8 J8 `8 F. Z% \4 E( o- M' F4 R9 @
5 L1 W1 ?; N) |. o9 e' Y
                Django在通常的SQL意义上不支持“联接”-它支持对象导航。9 \7 T" F2 E! B5 {& j
请注意,关系联接(内部或外部)会创建一个新的实体“类”。在Django中没有定义的一个。因此,没有适当的“结果集”,因为对于返回的内容没有类定义。您能做的最好的事情就是定义一个元组,对于缺少的组合,将在其中填充无。
* ]* g- u/ S' e8 ?) \, E8 z( X6 N左(或右)外部联接看起来像这样。它创建两个不相交的子集,一个具有一组关联的相关实体,另一个没有。
; S% @9 i. U( `for obj in Model1.objects.all():# M1 K! }1 @5 F& a- y2 O2 X' i. f" g" O
    if obj.model2_set().count() == 0:7 U, Z5 l4 E5 O; P" N1 f
        # process (obj, None) -- no Model2 association
, D! |) i. f; B0 M! b! \2 T* F+ G    else:
8 a$ m, K# O) S$ k3 R        for obj2 in obj.model2_set.all():2 L5 A0 o; e5 J2 u, Q4 A& ^
            # process (obj, obj2) -- the "inner join" result
, \! Q: d' |; \2 Z* Q' w“完全”外部联接是没有关系的其余项的并集。
5 J+ X% P9 f: S/ Q7 U6 j6 }/ Hfor obj2 in Model2.objects.all():
9 r7 B- Z8 I5 ?& I    if obj2.model1_set().count() == 0:
# I% o7 o2 p/ t5 E, O        # process (None, obj2) -- no Model1 association# |4 E+ V* Y7 ]. s8 U
问题始终是,您对这三个不同的对象子集的怪异集合正在做什么处理?7 M* M4 p8 X7 o  V& g; x
对象数据库的重点是将处理重点放在对象及其关联的对象上。
& ^7 n) @+ r' h9 |6 I8 M原始对象模型中从未存在称为“关系联接”的特殊集合。它是由两个(或多个)原始对象构建的一类新的对象。$ C% P& X) t' z
更糟糕的是,外部联接会创建具有多个子类的集合(内部联接,左外部联接和右外部联接)。那东西集合是什么 意思. f$ V5 W7 F, ?. A7 J8 S# b# g
等一下,情况可能会变得更糟。如果处理过程中包括对缺失属性的检查(即if someObj.anObj2attribute is# a% \2 I. s- `& K) Z6 H
None:我们本质上是在寻找Model1没有Model2对象关联的项目。嗯……为什么我们将它们放在外部联接中,仅使用if语句对其进行过滤?为什么不做呢?单独的查询和正确处理每个子集?
* \/ b. }; C' B9 r- c* `, ?
  h2 Q& J5 u. `* U编辑:当您显示“未完成”状态时,它根本不是外部联接。这要简单得多。您需要在视图函数中创建一个(或两个)单独的集合,以显示模板。
4 g( u+ x* W, N首先,您应该使用状态码,而不要使用是否存在外键。可选的外键没有“理由”-它们在那里或不在那里。状态代码可以提供有用的含义阴影(“不完整”,“错误”,“残破”,“不适用”,“要删除”等): a. L7 g4 S2 b
errorList1 = Model1.objects.filter( status="Incomplete" )
+ s9 w) o1 [. [errorList2 = Model2.objects.filter( status="Incomplete" )
) x' a9 F3 D0 V& i1 {( q这两个是完全外部联接的两个非联接部分。然后,您可以在模板中显示这两个错误列表,其中包含适当的列标题和状态代码以及所有内容。
. G- [+ |" r9 I/ s2 @! e* U您甚至可以将它们放在一个表中,以模仿人们过去看到的旧的完整外部联接报告& c$ a8 K& A7 j' }$ d
{% for e1 in errorList1 %}
0 _! D. ]4 T, u    {% endfor %}
3 T9 `) d, o/ h  }    {% for e2 in errorList2 %}+ z; d+ I/ Q+ V9 A+ r# z5 c( W9 W( U
    {% endfor %}
Model1Model2
e1NULL
NULLe2
' [7 U3 t9 A  P/ O
看起来像一个完整的外部联接报告。没有完整的外部联接。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则