Foreign Key Django Model

PythonDjangoDjango Models

Python Problem Overview


I'm trying to create 3 models ; Person, Address and Anniversy. The plan is to have one address and one anniversy for each person. But each address and anniversy can have multiple persons.

So far I have the following, but I think the OneToMany(foreign key) relationships maybe the wrong way round. i.e each address can have one person but each person can have multiple addresses.

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=50)
    birthday = models.DateField()

    def __unicode__(self):
        return u'%s' % (self.name)

class Address(models.Model):
    person = models.ForeignKey(Person)
    address = models.CharField(max_length=150)

    def __unicode__(self):
        return u'%s' % (self.address)

class Anniversy(models.Model):
    person = models.ForeignKey(Person)
    anniversy = models.DateField()

    def __unicode__(self):
        return u'%s' % (self.anniversy)

Python Solutions


Solution 1 - Python

You create the relationships the other way around; add foreign keys to the Person type to create a Many-to-One relationship:

class Person(models.Model):
    name = models.CharField(max_length=50)
    birthday = models.DateField()
    anniversary = models.ForeignKey(
        "Anniversary", on_delete=models.CASCADE)
    address = models.ForeignKey(
        "Address", on_delete=models.CASCADE)

class Address(models.Model):
    line1 = models.CharField(max_length=150)
    line2 = models.CharField(max_length=150)
    postalcode = models.CharField(max_length=10)
    city = models.CharField(max_length=150)
    country = models.CharField(max_length=150)

class Anniversary(models.Model):
    date = models.DateField()

I used string names for the other models so they can still be defined after, or you can define the Person model last.

Any one person can only be connected to one address and one anniversary, but addresses and anniversaries can be referenced from multiple Person entries.

Anniversary and Address objects will be given a reverse, backwards relationship too; by default it'll be called person_set but you can configure a different name if you need to. See Following relationships "backward" in the queries documentation.

Solution 2 - Python

I would advise, it is slightly better practise to use string model references for ForeignKey relationships if utilising an app based approach to seperation of logical concerns .

So, expanding on Martijn Pieters' answer:

class Person(models.Model):
    name = models.CharField(max_length=50)
    birthday = models.DateField()
    anniversary = models.ForeignKey(
        'app_label.Anniversary', on_delete=models.CASCADE)
    address = models.ForeignKey(
        'app_label.Address', on_delete=models.CASCADE)

class Address(models.Model):
    line1 = models.CharField(max_length=150)
    line2 = models.CharField(max_length=150)
    postalcode = models.CharField(max_length=10)
    city = models.CharField(max_length=150)
    country = models.CharField(max_length=150)

class Anniversary(models.Model):
    date = models.DateField()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionfelix001View Question on Stackoverflow
Solution 1 - PythonMartijn PietersView Answer on Stackoverflow
Solution 2 - PythonMicheal J. RobertsView Answer on Stackoverflow