Skip to main content

Make efficient and explicit SQL queries with the Django ORM automatically

Project description

django-orm-plus

PyPI version Python versions

A collection of useful ORM features to make using the Django ORM convenient, performant and safe

Installation

pip install django-orm-plus

Then add django_orm_plus to INSTALLED_APPS

Now you must do one of the following:

  1. Set AUTO_ADD_MODEL_MIXIN to True in settings.py:

    DJANGO_ORM_PLUS = {
        "AUTO_ADD_MODEL_MIXIN": True,
    }
    

    This will automatically patch your models with ORMPlusModelMixin

  2. Or, add the following model mixin to your models manually:

    from django.db import models
    from django_orm_plus.mixins import ORMPlusModelMixin
    
    
    class MyModel(models.Model, ORMPlusModelMixin):
        name = models.CharField(max_length=10)
    

Usage

This library has three 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. This method takes batch_size as an optional parameter which defaults to 1000

Configuration

You can set the following configuration object in settings.py:

DJANGO_ORM_PLUS = {
    "AUTO_ADD_MODEL_MIXIN": False,
    "STRICT_MODE_GLOBAL_OVERRIDE": None,
}

AUTO_ADD_MODEL_MIXIN is a boolean flag that will auto-patch all the models on load with ORMPlusModelMixin

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


Download files

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

Source Distribution

django-orm-plus-0.1.0b4.tar.gz (22.8 kB view hashes)

Uploaded Source

Built Distribution

django_orm_plus-0.1.0b4-py3-none-any.whl (11.5 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