title: Many-to-many relation on User table in Django
body: <p>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 <a href="https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships" rel="nofollow">specifying extra fields on M2M relationships</a>, but I can't wrap my head around what the model would look like.</p>
  
  <p>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:</p>
  
  <p>in models.py (psuedo-code, assume there is an Artist class):</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>then in views.py I save scores and common artists using something like (pseudo-code):</p>
  
  <pre><code>s = Score(user=u, second_user=second_user score=dh_score)
  s.save()
  </code></pre>
  
  <p>and retrieve them using something like:</p>
  
  <pre><code>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) &amp; Q(second_user=partner.id))\
                                             | (Q(user=partner.id) &amp; Q(second_user=u.id))
  )
  </code></pre>
  
  <p>What is the best way to accomplish this? </p>