2013-11-21 4 views
1

내가 가지고있는 것한 번에 여러 테이블을 쿼리하는 방법은 무엇입니까?

나는 체스 게임에서 토너먼트를 기록한 앱을 가지고있다.

(모든 플레이어가 모든 대회를 통해 재생과 일치 목록) tournament_view (목록 대회에서 연주 모두 일치) 및 player_view : 나는 두 개의 서로 다른 견해를 가질 계획 이제

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에는 필터 (선택 필터) playerAplayerB이 있으며 동적으로 선택 항목을 채워야합니다.

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

는 그러나, 나는 player_view에 대한 쿼리 마련하기 위해 고군분투이 쉽게 수행 할 수 있습니다. 이보기는 선택 필터 playerAplayerB과 매우 유사하지만 선택 사항으로 볼 때 모든 토너먼트 테이블을 조회해야 볼 수있는 플레이어의 모든 상대방을 얻을 수 있습니다. 이렇게하면 매번 데이터베이스 히트가 발생할 것이고 다른 테이블의 결과를 저장하고 추가하기 위해 임시 목록을 도입해야 할 것입니다.

그래서 내 모델을 재구성해야 할 필요가 있다고 생각하지만 내 마음에 오는 유일한 해결책은 모든 토너먼트의 경기가 함께 포장 된 거대한 테이블 하나를 만드는 것입니다.

제 질문은 내 모델을 조정하는 방법에 대한 아이디어가 있습니까? 아니면 장고가 player_view에 필요한 쿼리를 수행하는 솔루션을 제공합니까? 대신 두 개의 외래 키 필드를 갖는

답변

1

이,이 일 ManyToMany 필드 :

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() 

나는 그것이 문제의 대부분을 해결한다 생각하고, 아무 소용이 없기 때문에 또한 하나를 정의, 더 많은 의미가와 하나는 B 다. 둘 다 선수이고, 그들 사이에 예외적으로 구별 할 수있는 것이 없다.

+0

+1 나는 아직 언급하지 않았으므로 playerA는 일종의'player_at_home'을 의미하고'playerB'는'visitor'입니다. 나는 그것이 중요하다고 생각하지 않았지만 실제로 선수 들간의 구별을 원합니다. 당신은 당신의 솔루션이이 뉴스에 우선 할 것이라고 생각합니까? – nutship

+1

예, '통과'를 사용하여 중간 테이블을 사용해야합니다. 그것에 대해 읽어보십시오. (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. 

쿼리 결과에서 두 테이블의 정보가 필요한 경우에 좋지 않은 결정입니다. 하나의 tournamet 매치 또는 긍정적 인 스코어 매치 또는 특정 플레이어와의 매치를 쿼리하는 방법 (2 테이블 사용)에 대해 생각해보십시오. DB로드를 두 배로하는 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

장고를 사용하지는 않았지만 전에 실제로 이런 일을했습니다. 성냥의 숫자가 커질 때 모든 상대를 얻는 개념은 문제입니다.비행 중에 계산하지 않고도 이기심과 손실을 추적 할 수있는 솔루션을 활용할 수있었습니다.

www.eurosportscoreboard.com을 참조하십시오.

어쨌든, 내가 해결 한 방법은 트리거와 함께했습니다. 당신은 구원 신호로도 똑같이 할 수 있습니다.

모델을 만들고 fk 관계가 PlayerMatch 인 fk 관계로 만듭니다. Match이 저장되면 각 플레이어에 대해 Opponent을 만듭니다. 쓰기가 조금 느려지지만 읽는 속도가 매우 빠릅니다.

+0

롭이 묘사하고있는 것은 당신이 장고에서 ManyToMany가 어떻게 작동하는지 정확하게 묘사하고 있습니다. – yuvi

+0

내 자신을 위해 이것을 알아 내는데 정말 고생했습니다. – nutship

+1

또한 '아마추어'와 '마스터'가 별개의 모델이라고 생각해야한다고 생각합니다. 왜'Tournament.type = models.ForeignKey (TournamentType)'을 가지지 않는가? 그것은 더욱 유연해질 것입니다. 앞으로 귀하의 고객은 ProAm 토너먼트 등을 추가 할 수 있습니다. –

관련 문제