Ronald Langeveld
Ronald Langeveld

Reputation: 744

Django models, dealing with multiple foreign keys

I'm busy dealing with datasets based on Freshwater Lakes in the USA.

So my models are basically State and Lake. State being a foreign key in Lake.

As I started loading data, I quickly realised that it appears that some Lakes are bordering multiple states. Example Lake Erie goes into 4 states + an international border.

I then had to rethink my models a bit and came up with the following,

class State(models.Model):
    name = models.CharField(max_length=200, null=True)

    def __str__(self):
        return str(self.name)

class Lake(models.Model):
    state = models.ForeignKey(State, on_delete=models.CASCADE, verbose_name="primary state", related_name="related_primary_state", help_text="Primary State")
    state_secondary = models.ForeignKey(State, on_delete=models.CASCADE, null=True, blank=True, related_name="related_secondary_state", verbose_name="secondary state", help_text="Secondary State")
    state_three = models.ForeignKey(State, on_delete=models.CASCADE, null=True, blank=True, related_name="related_three_state", verbose_name="three state", help_text="three State")
    state_four = models.ForeignKey(State, on_delete=models.CASCADE, null=True, blank=True, related_name="related_four_state", verbose_name="four state", help_text="four State")
    state_five = models.ForeignKey(State, on_delete=models.CASCADE, null=True, blank=True, related_name="related_five_state", verbose_name="five state", help_text="five State")
    name = models.CharField(max_length=200, null=True)
    
    def __str__(self):
        return str(self.name)

Would this be okay to do, or are there better ways to approach this?

Thanks!

Upvotes: 0

Views: 77

Answers (1)

David Duran
David Duran

Reputation: 1826

You could better use a Many-to-many relationship like this:

class Lake(models.Model):
    states = models.ManyToManyField(State)
    name = models.CharField(max_length=200, null=True)
    
    def __str__(self):
        return str(self.name)

In this way you do not need to worry about how many states are foreigned key to a given lake. You could then associate as many states as you want to a given lake:

st1 = State(name="test1")
st1.save()
st2 = State(name="test2")
st2.save()
lk1 = Lake(name="lake1")
lk1.save()
lk1.states.add(st1, st2)

You can retrieve all states as follows:

>>>> lk1.states.all()
<QuerySet [<State: test1>, <State: test2>]>

See the documentation for full details: https://docs.djangoproject.com/en/3.0/topics/db/examples/many_to_many/

Upvotes: 3

Related Questions