Make efficient and explicit SQL queries with the Django ORM automatically
Project description
django-orm-plus
A collection of useful ORM features to make using the Django ORM convenient, performant and safe
Installation
pip install django-orm-plus
Now add the following model mixin to your models, eg:
from django.db import models
from django_orm_plus import ORMPlusModelMixin
class MyModel(models.Model, ORMPlusModelMixin):
name = models.CharField(max_length=10)
Usage
This library has two important functions for use on Django QuerySets:
.strict()
.fetch_related()
.bulk_update_or_create()
strict
Strict mode makes sure your ORM queries are efficient and safe by not allowing
related objects to be loaded lazily, therefore select_related
or prefetch_related
must be used if related objects are needed. This avoids
the n+1 query problem.
Strict mode will also raise an error when a deferred field (.defer()
or .only()
)
is accessed.
You only need to add .strict()
on your queryset wherever it's being used.
So for example in a DRF view:
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all().strict()
serializer_class = UserSerializer
permission_classes = [IsAdminUser]
Now your queryset is strict-mode enabled and your view will error if any relations
are loaded for the user queryset eg. users[0].profile
will error if profile
is a foreign key.
To fix, change the query to also fetch the relation using either select_related
or prefetch_related
:
queryset = User.objects.all().select_related("profile").strict()
fetch_related
Combines both select_related
and prefetch_related
to reduce the total number of queries for you automatically.
So instead of:
queryset = (
User.objects.all()
.select_related("profile")
.prefetch_related(
"likes",
Prefetch("books", queryset=Book.objects.all().select_related("author")),
)
)
It's now simply:
queryset = User.objects.all().fetch_related("profile", "likes", "books__author")
Of course, the two methods can be used together to get easy and safe queryset evaluation:
queryset = User.objects.all().fetch_related("profile", "likes", "books__author").strict()
Since select_related
does a join in SQL, fetch_related
opts to use select_related
when possible, and in other cases will use prefetch_related
which adds a single additional
query and does the join in Python.
bulk_update_or_create
updated, created = User.objects.bulk_update_or_create(
[User(username="john123", first_name="Jonny"), User(username="jane_doe", first_name="Alexa")],
lookup_fields=["username"],
update_fields=["first_name"],
)
This will combine bulk_update
and bulk_create
and return the records that were
updated and created. lookup_fields
is a list of field names that should uniquely
identify a record.
Configuration
You can set the following configuration object in settings.py
:
DJANGO_ORM_PLUS = {
"STRICT_MODE_GLOBAL_OVERRIDE": None,
}
STRICT_MODE_GLOBAL_OVERRIDE
is a boolean flag that will enable or disable strict
mode without considering if .strict()
is used. This can be useful if you want to
disable strict mode on production, or have all querysets use strict mode for local development.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django_orm_plus-0.1.0b2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9d19c37bf2457f458cc5a55ae2c4b866ed699d84ebfc3bac1c7cb4720991458e |
|
MD5 | f9bf31e7ab14ea0a92cc4e57f158eb5a |
|
BLAKE2b-256 | 86d5e31383301de1925cb83e126448d234f53646276da7fb2153dfcccc6d0619 |