2. Django Model Relationship Fields — Django 3 Tutorial Series for Beginners in 2021
There are 3 different relationship fields that we will talk about today. The many-to-many field, the many-to-one field, and the one-to-one field. These are used to specify the relationships between models. In this example we will specify different relationships between the Artist, Album, and Song models. For example, each song will have one album but each album can have multiple songs, so we will need a many to one field. Each Album can have multiple artists and each artist can have multiple albums so we will need a many to many field in that case. Let’s go through each of these fields one by one.
Many to Many Field
The first relationship field we will talk about is the many to many field, this field will be used to hold a relationship where both objects can have multiple of the other object. For example, in our example we will allow each artist to have multiple albums and we will let each album have multiple artists. So in this case we would need a many to many field. Django has a built in field for this. We can use this field and pass in the name of the model that we want to associate with. Here is an example:
class Artist(models.Model): name = models.CharField(max_length=100) email = models.EmailField(unique=True, null=True, blank=True) bio = models.TextField(null=True, blank=True, help_text='The bio for the artist') song_total = models.IntegerField(null=True, blank=True) choices = models.TextField(choices=[('1', 'Choice 1'), ('2', 'Choice 2')], null=True, blank=True) favorite = models.BooleanField(default=False) last_modified = models.DateTimeField(auto_now=True) created = models.DateTimeField(auto_now_add=True) profile_picture = models.ImageField(upload_to='uploads') download = models.FileField(upload_to='uploads')class Album(models.Model): title = models.CharField(max_length=100) released_on = models.DateTimeField(blank=True, null=True) artists = models.ManyToManyField('Artist')
You’ll see there is also an argument called on_delete. This tells Django what to do when an object is deleted, there are 6 options for this field, CASCADE, PROTECT, SET_NULL, SET_DEFAULT, SET(), DO_NOTHING. In this case we are using models.CASCADE, this will delete the other object when the object its associated with is also deleted, depending on the behavior of your application you may or may not want this to happen.
Adding, Deleting, and Getting Objects To/From This Field
First things first, make sure you migrate the changes to the database. You will also need to save the object in the database before these fields work, so make sure to call album.save() or whatever your object is called and then .save(). Once that is done, you can use the add method to add an object to the field. Here is an example:
album = Album(...)
album.artists.add(artist)
album.artists.add(artist, artist2)
You can either add them one at a time like what is being done in the second line in the example or you can add multiple by passing in more arguments like it is done in the third line. If you add it twice it will not duplicate the relationship. If you add an object that is different from what you specified in the many to many field, which in our case we passed in ‘Artist’, it will throw an exception.
To remove an object from the relationship, you can call the remove method, which works just like the add method except for removing objects. Here is an example.
album.artists.remove(artist)
Finally, you can get all objects in the relationship field using the add method. Here is an example:
album.artists.all()
There are other more advanced querying we can do but we will get into that later. There are also other options but this is the basics of using this field.
Many to One Field
This field is useful when we want one side of the relationship to store multiple objects but the other side should only be associated with one. We can do this with a ForeignKey field. In this example we will have a song model that will be associated with only one album but each album needs to have more than one song, so we need a many to one relationship here. Here is an example on how to use it:
class Song(models.Model): title = models.CharField(max_length=100) album = models.ForeignKey('Album', on_delete=models.CASCADE)
Once again, the on_delete option is required, we will set it to delete the associated object again. The arguments are very similar in all of the relationship fields. But this differs from the many to many field in how we add a relationship to it. For the song side of the relationship since there is only one associated to it, we can just add it like we would with any other field by setting a value using the = operator.
One to One Field
The last field we will talk about is the one to one field, this is good when only one object should be associated to both sides of the relationship. Here is an example of how to set up that field, it is pretty similar to the others:
class CatalogItem(models.Model): name = models.CharField(max_length=100) item = models.OneToOneField('Album', on_delete=CASCADE)
Once again, we specify the model type to associate to it and the on_delete option in the arguments. We can set this field using the = operator since there is only one per instance. So this should function similar to other fields.
This is just a quick overview on the basics of these fields, we will go back over some more advanced model concepts and querying next but this is necessary to understand before getting into those concepts. Hopefully this helps you get started using these fields.