2013-11-21 75 views
1

我有什麼如何一次查詢多個表?

我有一個應用程序,在國際象棋比賽檔案錦標賽。該應用程序包括以下型號:

class Tournament(models.Model): 
    name = models.CharField(max_length=128) 

class Player(models.Model): 
    name = models.CharField(max_length=128) 

# Abstract base class 
class Match(models.Model): 
    tournament = models.ForeignKey(Tournament) 
    playerA = models.ForeignKey(Player, related_name='%(class)s_A') # eg. mastertournament_A 
    playerB = models.ForeignKey(Player, related_name='%(class)s_B') 
    score = models.CharField(max_length=16) 

    class Meta: 
     abstract = True 

# here are tables of ``Match`` instances played out in a particular 
# tournaments. All ``Match`` instances share the same fields 
# so, I could also have one big table for all matches but I want to keep 
# each Tournament in separate table for easiness. 
class MasterTournament(Match): 
    pass 

class AmateurTournament(Match): 
    pass 

現在,我計劃有兩種不同的看法:tournament_view(名單在比賽中發揮的所有比賽)和player_view(列出所有匹配在所有賽事中玩家扮演)

要解決的問題

鑑於我提到的意見,我需要爲每個查詢執行兩個不同的查詢。 在tournament_view我會有篩選器(選擇篩選器)playerAplayerB,我需要爲它們動態地填充選項。

playersA_all = MasterTournament.objects.value_list('playerA') 
playersB_all = MasterTournament.objects.value_list('playerB') 

不過,我掙扎着拿出查詢player_view:這可以很容易地完成。此視圖與選擇過濾器playerAplayerB非常相似,但現在,我需要查詢所有錦標賽表以獲取正在查看的玩家的所有對手。這將導致每次都有一堆數據庫命中,在這個過程中,我需要引入一個臨時列表來保存和附加不同表中的結果。

這就是爲什麼我覺得我需要重新組織我的模型,但我唯一想到的解決方案是將所有錦標賽的比賽打包在一起,這是我想防止發生的事情。

我的問題是,你有任何想法如何調整我的模型,或者Django確實提供了一個解決方案來執行我需要的查詢player_view

回答

1

不是有兩個ForeignKey的領域,有一個多對多字段:

class Match(models.Model): 
    tournament = models.ForeignKey(Tournament) 
    players = models.ManyToManyField(Player, through='Participate') 
    score = models.CharField(max_length=16) 

class Participate(models.Model): 
    player = models.ForeignKey(Player) 
    match = models.ForeignKey(Match) 
    visitor = models.BooleanField() 

我認爲它解決了大部分的問題,也使得很多更有意義,因爲沒有點定義一個爲A,一個是B.兩個都是球員,他們之間沒有什麼特別的區別。

+0

+1,我還沒有接受,因爲我沒有提到它,但playerA意味着一種'player_at_home'和'playerB'是'visitor'。我不認爲這很重要,但我實際上想區分球員,我可能需要這樣做。這些消息你認爲你的解決方案會佔上風嗎? – nutship

+1

是的,但是您必須使用'through'來使用中間表。閱讀關於它[這裏](https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany) – yuvi

+0

看到編輯以及 – yuvi

0

你一次無法查詢多個表!您可以創建多個查詢和聯合結果。

# so, I could also have one big table for all matches but I want to keep 
# each Tournament in separate table for easiness. 

如果您需要查詢結果中的兩個表中的信息,這是一個糟糕的決定。想想你將如何查詢一個遊戲名稱匹配或正面比分匹配或與特定玩家匹配的2個表格 - 你必須對2個表格和聯合結果進行查詢,使數據庫負載翻倍。在這種情況下,你應該創建一個表的比賽,我想,併爲匹配類型一個領域 - 碩士或Amauter:

class Match(models.Model): 
    tournament = models.ForeignKey(Tournament) 
    playerA = models.ForeignKey(Player, related_name='%(class)s_A') # eg. mastertournament_A 
    playerB = models.ForeignKey(Player, related_name='%(class)s_B') 
    score = models.CharField(max_length=16) 
    master_or_amauter = models.BooleanField(default=True) # master by default 

並與一個表,你必須在player_view沒有問題... ...

+0

-1的聯合結果。對不起,但這是一個不好的答案。它並沒有真正回答這個問題,而且你也錯了,他的設計沒有任何壞處。如果他展示的是全部,那麼是的,你可能是對的。但是,使用抽象模型的概念意味着他可以爲每個特定於其自己類型的子模型添加其他字段。這不一定是一個糟糕的決定 – yuvi

+0

@ndpu,如果我有+10比賽會發生什麼?我想我需要爲每個表都有不同的表格。 – nutship

+0

@yuvi現在你錯了,你在想什麼? – ndpu

2

我之前已經做過這樣的事情,雖然我沒有使用Django來做。當比賽數量變大時,獲得所有對手的概念是一個問題。我能夠利用我的解決方案來跟蹤勝利和損失,而無需實時計算。

請參閱www.eurosportscoreboard.com。

無論如何,我解決它的方式是觸發器。你可以用保存信號做同樣的事情。

PlayerMatch創建一個帶有fk關係的Opponent模型。當保存Match時,爲每個玩家創建一個Opponent。寫入會有點慢,但讀取速度會非常快。

+0

Rob正在描述的是一個ManyToMany'通過'在django中工作的方法。 – yuvi

+0

謝謝你們爲我清理這件事,因爲我自己一直在想這件事,真的很痛苦! – nutship

+1

此外,我認爲你應該真的考慮'業餘「和」碩士「是不同的模型。爲什麼不用'Tournament.type = models.ForeignKey(TournamentType)'?這將會更加靈活。將來,您的客戶可能會添加ProAm錦標賽或其他內容。 –