Search code examples
djangodjango-querysetdjango-managers

django queryset method on related model filter


I have the following set-up:

class Person(models.Model):
  name

class AppointmentQuerySet(models.QuerySet):
  def active(self):
    from django.utils import timezone
    return self.filter(initial_date__date__lte=timezone.now().date())

class Appointment(models.Model):
  initial_date = models.DateTimeField()
  person = models.ForeignKey(Person, related_name='appointments', blank=True, null=True)
  objects = AppointmentQuerySet.as_manager()

  def active(self):
    from django.utils import timezone
    return self.initial_date <= timezone.now().date()

I fired up the shell to try some queries and created:

  • 1 person with no appointments
  • 2 person with 1 active appointment each

and tried this:

Person.objects.filter(appointments=True) 
# At some point yesterday, this was giving me results, 
# now it's returning an empty queryset

this works as I thought it would:

Person.objects.filter(appointments_isnull=False)
# returns the 2 persons with appointments but
# I have no clue from here if the appointments are active or not

If I try Person.objects.filter(appointments__active=True), I get:

FieldError: Related Field got invalid lookup: appointments

If instead, I try Person.objects.filter(appointments.active()=True), I get:

SyntaxError: keyword can't be an expression

How can I filter from Person.objects.filter(appointments=?) the active appointments each person has?


Solution

  • I ended up solving it creating a PersonQuerySet and a method, like so:

    class PersonQuerySet(models.QuerySet):
      def active_appointments(self):
        from django.utils import timezone
        return self.filter(appointments__initial_date__date__lte=timezone.now().date())
    

    It kinda sucks having to duplicate code tho.