Skip to main content

Django Queryset Constraint

Build Status Release Status License Python Versions Django Versions

This library enables one to write reliable data invariants, by compiling Django Querysets to database insert/update triggers, via. the migration system.

Motivation

Django has a built-in signal system, which emits signals on various events, for instance model creations, updates and deletions. However these signals are not emmited for queryset operations, and as such cannot be used to maintain data invariants.

An attempt to ratify this was made with the Django Queryset Signals library. While this library comes closer to a reliable solution, it does not succeed, as it is stil possible to break the data invariants by accessing the database directly.

Database Constraint Triggers will effectively protect against all scenarios.

Installation

pip install django_queryset_constraint

Usage

  • Add the django_queryset_constraint app to INSTALLED_APPS:
# settings.py
INSTALLED_APPS = {
    'django_queryset_constraint',
    ...
}

Note: This should be done before any apps that will be checked

  • Add QuerysetConstraint to constraints to the Meta class of the models to checked:
# models.py
from django.db import models
from django.db.models import Count
from django_queryset_constraint import M, QuerysetConstraint


class Topping(models.Model):
    name = models.CharField(max_length=30)


class PizzaTopping(models.Model):
    class Meta:
        unique_together = ("pizza", "topping")
        constraints = [
            # A pizza with more than 5 toppings gets soggy
            QuerysetConstraint(
                name='At most 5 toppings',
                queryset=M().objects.values(
                    'pizza'
                ).annotate(
                    num_toppings=Count('topping')
                ).filter(
                    num_toppings__gt=5
                ),
            ),
            # This constraint should be self-explanatory for civilized people
            QuerysetConstraint(
                name='No pineapple',
                queryset=M().objects.filter(
                    topping__name="Pineapple"
                )
            ),
        ]

    pizza = models.ForeignKey('Pizza', on_delete=models.CASCADE)
    topping = models.ForeignKey(Topping, on_delete=models.CASCADE)

class Pizza(models.Model):
    name = models.CharField(max_length=30)
    toppings = models.ManyToManyField(Topping, through=PizzaTopping)
  • Make migrations: python manage.py makemigrations
  • Run migrations: python manage.py migrate

Note: Complex triggers introduce performance overhead.

Support Matrix

This app supports the following combinations of Django and Python:

Django Python
2.2 3.6, 3.7

Metadata

Release files for django-queryset-constraint 1.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-queryset-constraint 1.0.6
File Size Uploaded Provenance Actions
django_queryset_constraint-1.0.6.tar.gz 14.3 kB Without provenance Details for django_queryset_constraint-1.0.6.tar.gz

Release files / django_queryset_constraint-1.0.6.tar.gz

Download URL django_queryset_constraint-1.0.6.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
3f21a6892890f25396941043096b1bb1a8b0d592aa36789587fb5df1613336a7
BLAKE2b-256 checksum
How to use checksums
fc9f56b1cc28a687b3f416b1c10c669fa8e859385a93de5b9dcebe94c403e8a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.4.0 requests-toolbelt/0.9.1 tqdm/4.40.2 CPython/3.6.8

Security for django-queryset-constraint 1.0.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page