Libby
Libby

Reputation: 581

Django model with many-to-one or none relationship vs many-to-many through?

I'm trying to build a application that lets people view tweets posted by politicians, and I'm struggling with the right way to specify the relationship between a user on Twitter and a user offline. For example, one politicians may have two Twitter accounts, and those accounts may mention three other Twitter users who are not politicians. Right now, I have a User table that contains info from the Twitter API (e.g., number of followers, number of tweets) that would have the Twitter info from both the politicians' accounts and those s/he mentioned and a Legislator table that contains info about legislators (e.g., party, chamber).

How would I set that model up correctly for Django? How do I access both user and legislator information in a template? With the setup below, I can't access anything in the legislator table from user.legislator_set.

class User(models.Model):
  id = models.IntegerField(primary_key=True)
  twitter_id = models.CharField(max_length=21, unique=True)
  twitter_name = models.CharField(max_length=55, unique=True)
  fullname = models.CharField(max_length=45)
  followers = models.IntegerField()
  following = models.IntegerField()
  favorites = models.IntegerField()
  tweets = models.IntegerField()
  timezone = models.CharField(max_length=45, blank=True)

class Legislator(models.Model):
  id = models.IntegerField(primary_key=True)
  last_name = models.CharField(max_length=17, blank=True)
  first_name = models.CharField(max_length=11, blank=True)
  chamber = models.CharField(max_length=3, blank=True)
  state = models.CharField(max_length=2, blank=True)
  party = models.CharField(max_length=11, blank=True)
  twitter_id = models.ForeignKey(User, to_field = "twitter_id", related_name="%(app_label)s_%(class)s_id")
  twitter = models.ForeignKey(User, to_field = "twitter_name", related_name="%(app_label)s_%(class)s_name")

Upvotes: 0

Views: 1691

Answers (1)

Brian
Brian

Reputation: 26

Libby. If I'm understanding your requirements, this seems like the simplest starting point -- a many-to-one relationship using a ForeignKey field. (This is basically the same thing as lanzz's suggestion.)

class User(models.Model):
  twitter_id = models.CharField(max_length=21, unique=True)
  twitter_name = models.CharField(max_length=55, unique=True)
  # ... other fields characterizing a Twitter account
  legislator = models.ForeignKey('Legislator', blank=True, null=True)

class Legislator(models.Model):
  last_name = models.CharField(max_length=17, blank=True)
  first_name = models.CharField(max_length=11, blank=True)
  # ... other fields characterizing a legislator

In your Python code, given a twitter account u and legislator l, you'd run u.legislator = l to associate a legislator with a twitter account. You could also express that as l.user_set.add(u), which makes more sense to me given these models.

Similarly, you'd use Legislator.user_setto access the RelatedManager for twitter accounts. This is what you'd loop over in a template or do additional queries against when you want to work with the related model (any/all related twitter accounts) instead of the one you have (a legislator).

There are a few more usage examples in the docs.

In the ForeignKey field, I set blank=True, null=True to make the relationship optional. Unless you specify otherwise in the field's options, Django will create and use a legislator_id column in the User table to manage the relationship.

Upvotes: 1

Related Questions