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.

Files for django-aggressivequery, version 0.3.2
Filename, size File type Python version Upload date Hashes
Filename, size django_aggressivequery-0.3.2-py3-none-any.whl (13.2 kB) File type Wheel Python version 3.4 Upload date Hashes View
Filename, size django-aggressivequery-0.3.2.tar.gz (9.7 kB) File type Source Python version None Upload date Hashes View

Supported by

Pingdom Pingdom Monitoring Google Google Object Storage and Download Analytics Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page