Skip to content

Instantly share code, notes, and snippets.

@mrob11
Last active October 27, 2020 11:22
Show Gist options
  • Save mrob11/9607834 to your computer and use it in GitHub Desktop.
Save mrob11/9607834 to your computer and use it in GitHub Desktop.
Simple follower/following relationship in Django
$ ./manage.py shell
Python 2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from followers.models import *
>>> john = User.objects.create_user('john', 'lennon@thebeatles.com', 'password')
>>> paul = User.objects.create_user('paul', 'mccartney@thebeatles.com', 'password')
>>> george = User.objects.create_user('george', 'harrison@thebeatles.com', 'password')
>>> ringo = User.objects.create_user('ringo', 'starr@thebeatles.com', 'password')
>>> john.following.add(Follower(following=paul))
>>> john.following.add(Follower(following=george))
>>> paul.following.add(Follower(following=john))
>>> ringo.following.add(Follower(following=john))
>>> ringo.following.add(Follower(following=paul))
>>> ringo.following.add(Follower(following=george))
>>> john.followers.all()
[<Follower: paul follows john>, <Follower: ringo follows john>]
>>> paul.followers.all()
[<Follower: john follows paul>, <Follower: ringo follows paul>]
>>> george.followers.all()
[<Follower: john follows george>, <Follower: ringo follows george>]
>>> john.following.all()
[<Follower: john follows paul>, <Follower: john follows george>]
>>> ringo.following.all()
[<Follower: ringo follows john>, <Follower: ringo follows paul>, <Follower: ringo follows george>]
>>> ringo.followers.all()
[]
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Follower(models.Model):
follower = models.ForeignKey(User, related_name='following')
following = models.ForeignKey(User, related_name='followers')
class Meta:
unique_together = ('follower', 'following')
def __unicode__(self):
return u'%s follows %s' % (self.follower, self.following)
@coci
Copy link

coci commented May 22, 2019

what is the following in john.following.add(.....) ?

@Elbekgithub
Copy link

very good

@Elbekgithub
Copy link

dwwdw

@kushagra219
Copy link

How can we ensure that follower and following are not same ??
Like John follows John doesn't make any sense?

@abd-koumare
Copy link

I think you can achieve that programmatically, you just have to check if the user that will follow John is not John itself

@abd-koumare
Copy link

I'm currently working on something like that if someone has a better solution I'm interested

@abd-koumare
Copy link

what is the following in john.following.add(.....) ?

django ORM provides some attributes and methods we don't have to use it if it makes no sense

@abd-koumare
Copy link

Follower.objects.create(follower=foo, following=bar)

@phongnm-0776
Copy link

phongnm-0776 commented Apr 3, 2020

Im new to django, but why the class name is Follower? Why not something like ProfileRelation or anything else different? Sr if my question doen't make sense.

@mrob11
Copy link
Author

mrob11 commented Apr 6, 2020

Im new to django, but why the class name is Follower? Why not something like ProfileRelation or anything else different? Sr if my question doen't make sense.

You can name it whatever you like. When I wrote this nearly 7 years ago it was just a very quick and dirty example to illustrate a many-to-many relationship between users. I was just quickly answering someone's question on Reddit I think. It seems to have gained some attention lately for some reason.

@mrob11
Copy link
Author

mrob11 commented Apr 6, 2020

How can we ensure that follower and following are not same ??
Like John follows John doesn't make any sense?

I would put a check in the Follower.save method to make sure follower and following are not the same user.

Edit: Actually, it's probably better to put that type of validation in a Model Form, or the Model's clean method rather than the Model save method.

@jibachhydv
Copy link

jibachhydv commented Sep 4, 2020

def clean(self):
        if self.follower == self.following:
            raise ValidationError("One Cannot follow themselves")

This can be a one way

@mrob11
Copy link
Author

mrob11 commented Sep 9, 2020

Yeah that looks pretty clean. No pun intended.

@Olamidun
Copy link

Hi Mike, why did you choose to use ForeignKey instead of ManyToMany Relationship?
A user should be able to follow multiple users and multiple users should also be able to follow a user. Is using a foreignkey not going to restrict it to just one user being able to follow multiple users and multiple users not being able to follow a user...or vice versa?

@mrob11
Copy link
Author

mrob11 commented Sep 18, 2020

@Olamidun if I chose a ManyToMany field, that would have to have been implemented directly on the User model which is an unnecessary complication. This method is essentially a through model on a M2M field without declaring it that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment