I'm using Django Managers to make a higher API to interact with my database and keeping my code cleaner and more readable. But in case I have a Foreignkey
relationship, I can't use the manager of the ForeignKey model. The queries are more complex as below, but I just simplified the example so, It can be easier to read and get the idea of the question:
models.py:
class Community(models.Model):
objects = CommunityManager()
...
class Inscription(models.Model):
objects = InscriptionManager()
...
community = models.ForeignKey("Community", related_name="inscriptions")
created_at = models.DateTimeField()
managers.py:
from datetime import date
from django.db import models
class InscriptionQuerySet(models.query.QuerySet):
def by_day(self, day=date.today()):
return self.filter(created_at__day=day)
... # more queries
class InscriptionManager(models.Manager):
def get_query_set(self):
return InscriptionQuerySet(self.model, using=self._db)
def today(self):
return self.get_query_set().by_day()
... # more queries
class CommunityQuerySet(models.query.QuerySet):
def by_type(self, type):
return self.filter(type=type)
... # more queries
class CommunityManager(models.Manager):
def get_query_set(self):
return OrganistaionQuerySet(self.model, using=self._db)
def by_type(self, type):
return self.get_query_set().by_type(type)
... # more queries
Usage:
Inscription.objects.by_day() # return correctly all the inscriptions made today
Community.objects.by_type('type1') # return correctly all Communities that match
Problem: but here lies the problem
community_b = Community.objects.get(id=12)
community_b.inscriptions.by_day()
>>> AttributeError: 'ForeignRelatedObjectsDescriptor' object has no attribute 'by_day'
How can I fixe this. How to customize the manager to take in consideration the models relation.
I don't see the need of both Manager
and QuerySet
in your approach. You could just do away with a QuerySet
. This is how I generally implement custom managers, and I tried accessing custom manager method on reverse relationship in one of my projects, and it works fine:
class InscriptionQuerySet(models.QuerySet):
def by_day(self, day=date.today()):
return self.filter(created_at__day=day)
def today(self):
return self.by_day()
class CommunityQuerySet(models.QuerySet):
def by_type(self, type):
return self.filter(type=type)
And then in your models, change your objects
like this:
class Community(models.Model):
objects = CommunityQuerySet.as_manager()
...
class Inscription(models.Model):
objects = InscriptionQuerySet.as_manager()
I think you would be able to access custom queryset method with this setup.