2011-04-13 66 views
0

假设模型X有一个字段n(整数)。现在我也有一个模型Y其中有nm(整数)字段。是否有可能使用Django ORM选择x(型号X),从而存在y(型号Y),使得x.n = y.ny.m = mm给定值?Django模型中的任意连接

请不要建议我介绍两个模型之间的关系ForeignKey或类似的东西。我想知道是否可以在不修改模型的情况下实现这一点。在我正在处理的具体情况中,给定的关系是通用的。而通用关系的另一面可以是任何东西,所以根据文档我不能在不同的模型中多次引入GenericRelation

+0

难道只有我或者这是在功能上有严重的差距?它怎么可能不是微不足道的?我开始认为他们将代码保存在svn中的事实是一个不好的迹象。 – julkiewicz 2011-04-13 16:51:57

+0

在Django世界中,限制比你想象的要少。如果你想进行任意连接,原始SQL(返回真正的模型对象)就在你身边。而且......你知道,我也喜欢git和Mercurial,但是如果说对开源项目最大的抱怨是它对源代码控制工具的喜爱,那么人们已经达到了天堂。 – Christophe 2011-09-05 17:14:07

+0

@Christophe原始SQL的问题是,您需要手动生成表名,手动创建列名。我认为它会使当前的交易变得肮脏。我知道这是可能的,但是如果每次我需要做一些非标准的事情时,我都需要手工编写SQL,我宁愿不使用ORM。经过与Django ORM的相当一段时间之后,我认为它被设计严重破坏了。 – julkiewicz 2011-09-06 00:47:32

回答

4

我想这可以实现usi ng extraQuerySet方法。

(我没有测试过)

X.objects.extra(where=["x.n in (select y.n from y where y.m = '%s')"], params=['m_value']) 
+0

那么,它在命名中稍作改动后就可以工作。根据我阅读的内容,它的表现也比常规的JOIN更好。谢谢。 – julkiewicz 2011-04-13 16:50:02

+0

queryset.query.get_initial_alias()获取分配给查询中主表的别名。 SomeModel._meta.db_table也具有任何模型的基础表名称。 – 2018-01-19 17:33:53

1

为此,您可以使用原始SQL:使用ORM

def my_custom_sql(m): 
    from django.db import connection, transaction 
    cursor = connection.cursor() 

    # Data retrieval operation - no commit required 

    command = """SELECT * 
     FROM tX 
INNER JOIN tY 
     ON (tX.n=tY.n AND tY.m=%s)""" 

    cursor.execute(command % str(m)) 
    rows = cursor.fetchall() 

    return rows 

,我认为你可以做到这一点使用values_listin过滤器:

class X(models.Model): 
    n = models.IntegerField() 

class Y(models.Model): 
    n = models.IntegerField() 
    m = models.IntegerField() 

xs = X.objects.filter(n__in=Y.objects.filter(m=m).values_list('n')).distinct() 

编辑: 如前所述在评论中,这种方法将击中分贝很多

+1

只需要注意一下:做@kriegar在那里做的第二种方式会导致每个X对象的数据库O(n + 1)命中,超级糟糕!并强烈建议不要这样做。你应该使用他发布的第一种方法。 – 2011-04-13 11:45:47

+0

那么,第二种方式的问题是,它只是非常低效,因为它可能会将很长的值列表传输到数据库...第一种方法,以及我没有选择。也许我会试着把它打包成一个经理。不过,我认为我开始对这个框架产生仇恨。哎呀! – julkiewicz 2011-04-13 11:49:29