Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to add record to many to many relationship in Django

First off, I'm planning on running my project on google app engine so I'm using djangoappengine which as far as I know doesn't support django's ManyToManyField type. Because of this I've setup my models like this:

from django.db import models
from django.contrib.auth.models import User

class Group(models.Model):
    name = models.CharField(max_length=200)

class UserGroup(models.Model):
    user = models.ForeignKey(User)
    group = models.ForeignKey(Group)

On a page I have a form field where people can enter a group name. I want the results from this form field to create a UserGroup object for the user - group combination and if the group doesn't yet exist create a new Group object. At first I started putting this logic in the UserGroup class with a add_group method but quickly realized that it doesn't really make sense to put this in the UserGroup class. What would the proper way of doing this be? I saw some stuff about model managers. Is this what those are for?

like image 821
Ian Burris Avatar asked Dec 17 '25 04:12

Ian Burris


1 Answers

From the Django docs:

A Manager is the interface through which database query operations are provided to Django models

So a manager is not the way to create new instances of a model.

I would just have a constructor for the Group model which pulls the User (if it is given) from the keyword arguments and creates a new UserGroup.

So if you instantiated a new Group as Group(name='group name', user=some_user) the constructor could strip the user keyword argument away and create the appropriate UserGroup with that user:

class Group(models.Model):
    name = models.CharField(max_length=200)

    def __init__(self, *args, **kwargs):
        # Remove user from the kwargs.
        # It is important that user is removed from the kwargs before calling
        # the super.__init__(). This is because the `user` kwarg is not expected.
        user = kwargs.pop('user', None)

        # call the normal init method
        super(Group, self).__init__(*args, **kwargs)

        # Create the UserGroup instance for the specified user
        if user is not None:
            # Maybe some other logic here ...
            UserGroup(user=user, group=self).save()

This way if you provide a user when instantiating your Group it will create a UserGroup and will do nothing otherwise.

Of course you could equally do a similar thing in the constructor of the UserGroup model, it is not really that important, it just depends which metaphorically makes sense to your code.

EDIT:

A fix to the problems pointed out in the comments:

...
def __init__(self, *args, **kwargs):
    ...
    self._user_group = UserGroup(user=user, group=self)

def save(self, *args, **kwargs):
    super(Group, self).save(*args, **kwargs)
    self._user_group.save()
like image 108
Marcus Whybrow Avatar answered Dec 19 '25 18:12

Marcus Whybrow



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!