Django中用户表中的多对多关系 [英] Many-to-many relation on User table in Django
问题描述
这是我目前所完成的,假设不是最好的方法,因为它需要为每个查询通过数据库两次传递:
在models.py(psuedo-code,假设有一个艺术家类):
class UserProfile(models.Model):
user = models.OneToOneField(User)
zipcode = models.CharField(max_length = 16)
def create_user_profile(发件人,实例,创建,** kwargs):
如果创建:
profile,created = UserProfile。目的s.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 =真)
deleted = models.BooleanField()
然后在views.py我保存分数和常见艺术家使用(伪代码):
s =得分(user = u,second_user = second_user score = dh_score)
s.save()
并使用以下方式检索它们:
u = User.objects.get(username =%s%username)
user_scores = Score.objects.filter(Q(用户= u.id)| Q(second_user = u.id)).order_by(' - dh_score')[:10]
在user_scores中的user_score:
#确定谁是用户和谁是谁的相关逻辑是伙伴
...
partner_artists = UserArtist.objects.filter((Q(user = u.id)& Q(second_user = partner.id))\
|(Q(user = partner.id)& Q(second_user = u.id))
)
最好的方法是什么?
这是我如何完成用户到用户的数据配对,以及与中间表建立M2M关系:
models.py
from django.db import models $来自django.contrib.auth.models的b $ b从django.db.models.signals导入的用户
import post_save
class UserProfile(models.Model):
user = models .OneToOneField(User)
pair = models.ManyToManyField('self',through ='PairData',symmetric = False)
def __unicode __(self):
返回%s的个人资料%self.user
def create_user_profile(发件人,实例,创建,** kwargs):
如果创建:
profile,created = UserProfile。 object.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)
类艺术家(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_prof ile)| 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,请分享!
I'm writing an app where I need to associate data with user pairs. For instance, each user pair will have a compatibility score associated with them, as well as many-to-many relationships such as artists that they have in common. I'm confused about the best way to do this, it seems like I would use a combination of 1) extending User via the one-to-one relationship, 2) using a recursive relationship to self on the User table, 3) coupled with specifying extra fields on M2M relationships, but I can't wrap my head around what the model would look like.
This is how I am accomplishing this currently, which I assume is not the best way to do it as it requires two passes through the DB for each query:
in models.py (psuedo-code, assume there is an Artist class):
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()
then in views.py I save scores and common artists using something like (pseudo-code):
s = Score(user=u, second_user=second_user score=dh_score)
s.save()
and retrieve them using something 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))
)
What is the best way to accomplish this?
Here is how I accomplished the user-to-user data pairing, as well as making a M2M relationship to the intermediate table:
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
Here is an example of how I queried the pair data (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')
and the artists associated with each pair:
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)
If there is a better way to query without using Q, please share!
这篇关于Django中用户表中的多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!