2011-04-13 84 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