django-modelsmany-to-manypython-3.9django-3.2

models.ManyToManyField Necessity


I can't understand, what benefits we get when adding models.ManyToManyField if using intermediary model? Is it necessary? I want to use base (not custom) user model in my project. Should I redefine CustomUser for this single field? I read docs and have found no information about using only intermediary model, but it works. I tried to skip CustomUser model and use User in Follow model. It works perfectly fine. Big thank you for the answers!

class CustomUser(AbstractUser):
    follow = models.ManyToManyField(
        'self', through='Follow', symmetrical=False
    )

class Follow(models.Model):
    user = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE, related_name='followers'
    )
    following = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE, related_name='following'
    )
    created = models.DateTimeField(
        'Creation Time', auto_now_add=True, null=True
    )

What's the difference between this options?

User = get_user_model()

class Follow(models.Model):
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='followers'
    )
    following = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='following'
    )
    created = models.DateTimeField(
        'Creation Time', auto_now_add=True, null=True
    )

Solution

  • Is it necessary?

    No, a ManyToManyField essentially creates an intermediate table when none is specified. But...

    I can't understand, what benefits we get when adding models.ManyToManyField if using intermediary model?

    It allows faster querying. Indeed, now we can use:

    CustomUser.objects.filter(follow=my_other_user)

    without this ManyToManyField, it would require using:

    CustomUser.objects.filter(followers__following=my_other_user)

    which thus makes querying elegant: it will boil down to the same SQL query, so it is not more efficient, but it requires less writing.

    It also means that ModelForms and ModelAdmins, will make the relation editable in the CustomUser model admin for example, and thus one can pick items out of a list of choices.

    Using a custom model for a ManyToManyField however, might indeed be a bit overkill.