Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to run a custom get_queryset method with django-auto-prefetch? #275

Closed
nickmccullum opened this issue Oct 9, 2023 · 6 comments

Comments

@nickmccullum
Copy link

Python Version

3.10

Django Version

4.2.6

Package Version

1.7.0

Description

I am trying to integrate django-auto-prefetch with a Django project that has a soft deletion framework.

This doesn't work (i.e., it uses the regular Django query functionality.

import auto_prefetch


class NotDeletableManager(auto_prefetch.Manager):
    def get_queryset(self) -> models.QuerySet:
        return super().get_queryset().filter(deleted_at__isnull=True)

any tips?

@tolomea
Copy link
Owner

tolomea commented Oct 9, 2023 via email

@nickmccullum
Copy link
Author

Here are answers to your questions:

  • This is custom code in our project, used in an abstract model that is inherited by many other models. It looks like this (before the django-auto-prefetch integration):
class DeletedObjectsManager(models.Manager):
    def get_queryset(self) -> models.QuerySet:
        return super().get_queryset().filter(deleted_at__isnull=False)


class NotDeletableManager(models.Manager):
    def get_queryset(self) -> models.QuerySet:
        return super().get_queryset().filter(deleted_at__isnull=True)


class NotDeletableMixin(models.Model):
    """
    A framework for soft deletion in Django.
    """

    objects = NotDeletableManager()
    deleted_objects = DeletedObjectsManager()
    all_objects = models.Manager()
  • That NotDeletableMixin is inherited by other models
  • We use django-perf-rec to monitor the SQL queries performed across our entire test suite. This setup did not create any changes to the SQL used in our app:
import auto_prefetch


class DeletedObjectsManager(auto_prefetch.Manager):
    def get_queryset(self) -> models.QuerySet:
        return super().get_queryset().filter(deleted_at__isnull=False)


class NotDeletableManager(auto_prefetch.Manager):
    def get_queryset(self) -> models.QuerySet:
        return super().get_queryset().filter(deleted_at__isnull=True)


class NotDeletableMixin(auto_prefetch.Model):
    """
    A framework for soft deletion in Django.
    """

    objects = NotDeletableManager()
    deleted_objects = DeletedObjectsManager()
    all_objects = models.Manager()

However, this setup did result in new SQL being generated:

import auto_prefetch


class NotDeletableMixin(models.Model):
    """
    A framework for soft deletion in Django.
    """

    objects = auto_prefetch.Manager()
    deleted_objects = auto_prefetch.Manager()
    all_objects = auto_prefetch.Manager()

which leads me to believe there might be a problem with the get_queryset method.

Hopefully this help!

@tolomea
Copy link
Owner

tolomea commented Oct 9, 2023 via email

@nickmccullum
Copy link
Author

that's a good point.

I am going to specifically set up a test case that should trigger an N+1 query, and see what the behavior is. I'll update you eventually.

@nickmccullum
Copy link
Author

Bah, you're right. this is working as intended.

I used django-perf-rec to profile this code:

with django_perf_rec.record():
    rental_units = RentalUnit.objects.all()
    [rental_unit.building.property_management_company for rental_unit in rental_units]

which should absolutely create an N+1 query under Django's standard configuration. However, only 3 queries were performed. Here's the .yml output:

test_auto_prefetch:
- db: 'SELECT ... FROM "rental_unit" WHERE "rental_unit"."deleted_at" IS #'
- db: SELECT ... FROM "building" WHERE "building"."id" IN (...)
- db: SELECT ... FROM "property_management_company" WHERE "property_management_company"."id" IN (...)

Closing this issue now. Thanks for your time.

@tolomea
Copy link
Owner

tolomea commented Oct 9, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants