2012-03-28 12 views
1

私はデータをユーザのペアと関連付ける必要があるアプリケーションを書いています。たとえば、各ユーザーペアには、それらに関連付けられた互換性スコアだけでなく、共通点を持つアーティストなどの多対多の関係もあります。私はこれを行うための最良の方法について混乱している、それは1)1対1の関係を介してユーザーを拡張する、2)ユーザーテーブルの自己への再帰的な関係を使用する、3)結合するspecifying extra fields on M2M relationshipsとなりましたが、私はモデルがどのように見えるかを頭で覆すことはできません。 models.pyにDjangoのUserテーブルの多対多の関係

(擬似コード、想定しています

これは私が、私はそれがDBを2回通過を必要とする各クエリのためにそれを行うための最善の方法ではないと仮定しており、現在、これを達成しています方法です

s = Score(user=u, second_user=second_user score=dh_score) 
s.save() 

と何かを使用してそれらを取得します)

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    zipcode = models.CharField(max_length=16) 

def create_user_profile(sender, instance, created, **kwargs): 
    if created: 
     profile, created = UserProfile.objects.get_or_create(user=instance) 

post_save.connect(create_user_profile, sender=User)   

class Score(models.Model): 
    user = models.ForeignKey(User, related_name='score_first_user') 
    second_user = models.ForeignKey(User, related_name='score_second_user') 
    dh_score = models.DecimalField(decimal_places=2, max_digits=5) 
    cre_date = models.DateTimeField(auto_now_add=True) 
    upd_date = models.DateTimeField(auto_now=True) 
    deleted = models.BooleanField() 

    class Meta: 
     unique_together = ('user', 'second_user') 

class UserArtist(models.Model): 
    user = models.ForeignKey(User, related_name='userartist_first_user') 
    second_user = models.ForeignKey(User, related_name='userartist_second_user') 
    artist = models.ForeignKey(Artist) 
    cre_date = models.DateTimeField(auto_now_add=True) 
    upd_date = models.DateTimeField(auto_now=True) 
    deleted = models.BooleanField() 

は、views.pyに私は(擬似コードのようなものを使用してスコアと共通のアーティストを保存:そこアーティストクラス)がありますlike:

u = User.objects.get(username="%s" % username) 
user_scores = Score.objects.filter(Q(user=u.id) | Q(second_user=u.id)).order_by('-dh_score')[:10] 

for user_score in user_scores: 
# non-relevant logic to determine who is user and who is partner 
... 

    partner_artists = UserArtist.objects.filter((Q(user=u.id) & Q(second_user=partner.id))\ 
              | (Q(user=partner.id) & Q(second_user=u.id)) 
) 

これを行うにはどのような方法が最適ですか?ここ

+0

誰かが私が質問していた答えを提供しました。これは修正を使って終了したものです。実装してテストする前に削除しましたが、まだそこにいる場合は再追加して受け入れることができます。 – kasceled

答えて

4

私はユーザ対ユーザデータのペアリングを達成し、ならびに中間テーブルにM2M関係を製造する方法である:ここ

models.py

from django.db import models 
from django.contrib.auth.models import User 
from django.db.models.signals import post_save 

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    pair = models.ManyToManyField('self', through='PairData', symmetrical=False) 


    def __unicode__(self): 
     return "%s's profile" % self.user 

def create_user_profile(sender, instance, created, **kwargs): 
    if created: 
     profile, created = UserProfile.objects.get_or_create(user=instance) 

post_save.connect(create_user_profile, sender=User) 

class PairData(models.Model): 
    first_user = models.ForeignKey(UserProfile, related_name='first_user') 
    second_user = models.ForeignKey(UserProfile, related_name='second_user') 
    raw_score = models.DecimalField(decimal_places=4, max_digits=9) 
    dh_score = models.DecimalField(decimal_places=2, max_digits=5) 
    distance = models.PositiveIntegerField() 
    cre_date = models.DateTimeField(auto_now_add=True) 

    def __unicode__(self): 
     return u"%s %s %f %d" % (self.first_user, self.second_user, self.dh_score, self.distance) 

class Artist(models.Model): 
    pair = models.ManyToManyField(PairData) 
    artist_name = models.CharField(max_length=256) 

    def __unicode__(self): 
     return u"%s" % self.artist_name 

は方法の例であります私は(views.py)対データを照会:

def matches(request, username): 
    user_profile = User.objects.get(username=username).get_profile() 
    pd = PairData.objects.filter(Q(first_user=user_profile) | Q(second_user=user_profile)).order_by('-dh_score') 

各対に関連アーティスト:

def user_profile(request, username): 
    user_profile = User.objects.get(username=username).get_profile() 
    viewers_profile = request.user.get_profile() 

    pair = PairData.objects.filter((Q(first_user=user_profile) & Q(second_user=viewers_profile)) \ 
            | (Q(first_user=viewers_profile) & Q(second_user=user_profile))) 

    artists = Artist.objects.filter(pair=pair) 

Qを使用せずに照会するより良い方法があれば、共有してください!