Skip to main content

handling select_related and prefetch_reated, semi-automatically

Project description

(this is experimental package)

handling select_related and prefetch_reated, semi-automatically.

from django_aggressivequery import from_queryset
(
    from_queryset(UserInfo.objects.filter(point__gt=0), ["user__teams__games"])
    .prefetch_filter(
        user__teams__games=lambda qs: qs.filter(name__contains="-a")
    )
)

# almost same means
from django.db.models import Prefetch
(
    UserInfo.objects.filter(point__gt=0)
    .select_related("user")
    .prefetch_related(
        "user__teams",
        Prefetch("user__teams__games", queryset=Game.objects.filter(name__contains="-a"))
    )
)

SQL example

SELECT
 "userinfo"."id", "userinfo"."point", "userinfo"."ctime", "userinfo"."user_id",
 "user"."id", "user"."name", "user"."ctime"
FROM "userinfo"
INNER JOIN "user" ON ("userinfo"."user_id" = "user"."id")
WHERE "userinfo"."point" > 0;
SELECT
 ("team_users"."user_id") AS "_prefetch_related_val_user_id",
 "team"."id", "team"."name", "team"."price", "team"."ctime"
FROM "team"
INNER JOIN "team_users" ON ("team"."id" = "team_users"."team_id")
WHERE "team_users"."user_id" IN (2);
SELECT
"game"."id", "game"."team_id", "game"."name", "game"."price", "game"."ctime"
FROM "game"
WHERE ("game"."name" LIKE '%-a%' ESCAPE '\' AND "game"."team_id" IN (1, 2));

model

# relation: UserInfo - User *-* Team -* Game
class User(models.Model):
    name = models.CharField(max_length=255, default="", null=False)
    ctime = models.DateTimeField()

class UserInfo(models.Model):
    point = models.IntegerField(null=False, default=0)
    user = models.OneToOneField(User, related_name="info")
    ctime = models.DateTimeField()

class Team(models.Model):
    users = models.ManyToManyField(User, related_name="teams")
    name = models.CharField(max_length=255, default="", null=False)
    price = models.IntegerField(null=False, default=0)
    ctime = models.DateTimeField()

class Game(models.Model):
    team = models.ForeignKey(Team, related_name="games")
    name = models.CharField(max_length=255, default="", null=False)
    price = models.IntegerField(null=False, default=0)
    ctime = models.DateTimeField()

more specific option

Calling from_queryset() with more_specific option, then use Query.only().

from django_aggressivequery import from_queryset
(
    from_queryset(UserInfo.objects.filter(point__gt=0), ["point", "user__name", "user__teams__name", "user__teams__games__name"], more_specific=True)
    .prefetch_filter(
        user__teams__games=lambda qs: qs.filter(name__contains="-a")
    )
)

0.3.1:

  • fix bug when unexpected relations are found.

0.3.0: - fix bug that duplicated hints are occured - fix bug that get_accessor_name() method is not used - adding extension feature. - reimplementing skip_filter() as extension - implementing custom_prefetch() as extension - reimplementing prefetch_filter() as extension - (module separation)

0.2.0: - skipping function support (AggressiveQuery.skip_filter())

0.1.2: - gentle type check, in from_query()

0.1.1 - remove need less join (on prefetch releated)

0.1 - first release

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-aggressivequery-0.3.1.tar.gz (9.7 kB view hashes)

Uploaded Source

Built Distribution

django_aggressivequery-0.3.1-py3-none-any.whl (13.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page