Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I add a manager to a manytomany relationship?

I have two models that has a manytomany relationship with a 'through' table in some way?

class Bike(models.Model):
   nickname = models.CharField(max_length=40)
   users    = models.ManyToManyField(User, through='bike.BikeUser')

The BikeUser class

class BikeUser(models.Model):
   bike     = models.ForeignKey(Bike)
   user     = models.ForeignKey(User)
   comment  = models.CharField(max_length=140)

I would like to add functionality to the Bike class for working with users, is there a best practice way of doing this. I would like to avoid adding too many methods to the Bike class and rather have some kind of manager to work through

Something like:

bike.bikeusers_set.commonMethod()

or

bike.bikeusers.commonMethod()

What would be the best way to accomplish this?

like image 871
Joelbitar Avatar asked Oct 02 '10 13:10

Joelbitar


2 Answers

Once you have the BikeUser model, you can add a custom manager to the model.

Something like:

class BikeUserManager(models.Manager):
    def commonMethod():
        pass

class BikeUser(models.Model):
   bike     = models.ForeignKey(Bike)
   user     = models.ForeignKey(User)
   comment  = models.CharField(max_length=140)
   objects  = BikeUserManager()

But you can only use it from the BikeUser Model:

BikeUser.objects.commonMethod()

What you want is to use this manager as a related manager: http://docs.djangoproject.com/en/dev/topics/db/managers/#controlling-automatic-manager-types

Add the use_for_related_fields=True to the manager class.

class MyManager(models.Manager):
    use_for_related_fields = True
like image 200
OmerGertel Avatar answered Oct 02 '22 12:10

OmerGertel


use_for_related_fields is deprecated from django 2.0. Use for related fields is possible via base manager.

old:

class CustomManager(models.Model):
    use_for_related_fields = True

class Model(models.Model):
    custom_manager = CustomManager()

new:

class Model(models.Model):
    custom_manager = CustomManager()

    class Meta:
        base_manager_name = 'custom_manager'

source of example

Remember about restrictions for get_queryset() method.

like image 32
MartinP Avatar answered Oct 02 '22 13:10

MartinP