Ishan Tiwari
Posted on July 25, 2022
Relationships become really tricky if you have a data managing backend with scores of data to handle with interconnections. This post tends to remove that jargon from your head.
There are a lot of ways to do handle a thing in django. One is the opinionated way and other ways are potholes to look our for. So, we will discuss the use cases for using these relationships as well. Let's go.
Foreign keys and reverse accessors.
If you must have seen a error during this type of code in Django.
class Post(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE)
receiver = models.ForeignKey(User, on_delete=models.CASCADE)
The error should say that, "Reverse accessor for 'Post.sender' clashes with reverse accessor for 'Post.receiver'."
The thing is that django does not know how to access a users created posts(i.e the posts they are a sender of) and how to access their received posts (i.e the posts they are a receiver of).
To solve this confusion it is best to add a related_name argument. This let's you access a users received and sent posts.
class Post(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sentposts')
receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='receivedposts')
This way you can access the sent and received posts via
alan = User.objects.get(pk=1) #Got the user
posts_sent = alan.sentposts #Got the posts!!
One to One relationships and illegal accounts
Suppose you have a nice twitter like app you want add more functionality to the user perhaps give him his own profile picture a bio and all that you want to have a profile for him. So you do this -:
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="profile")
bio = models.CharField(max_length=400)
Everything just looks fine here, but this is a big mistake.
This mistake marks the difference between all these joins.
Here, you not only want a Profile to be associated with a user but a unique user. Here, at least theoretically a user can have another Profile which is just as much his. You can stop that in the Frontend but what's the point if you can stop that in the backend. For a user to have a profile you can do.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
bio = models.CharField(max_length=400)
This saves your time your brain and your app.
Many to Many Fields and Technical Jargon
Suppose you want a book library app. A book can be written by many authors and an author can also write many books. One To One relationship won't at all work, so will Foreign Key because after all it is just a property like a post can have a single sender and a receiver that's clear what many people do is have an intermediary like this -:
class Author_list(models.Model):
Author1 = models.ForeignKey(User, related_name="author1")
Author2 = models.ForeignKey(User, related_name="author2"
class Book(models.Model):
author = models.ForeignKey(Author_list)
As you can see this method can just accommodate a few authors and what do you do if a book has just one? Maybe set a few things to a null able value and then try. This method can is vulnerable to a lot of scale related issues. Instead just user the Many To Many relationship.
All that is different between this and Foreign Key is that Foreign stores one value as column in your database and this stores a whole list of them. Think of it as a list of users who have written their masterpiece.
class Book(models.Model):
author = models.ManyToMany(User, related_name="books")
Conclusion
Hope you enjoyed reading the post. Many many happy wishes for your relationship with django.
Posted on July 25, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.