Skip to main content
Seal
Build Status Coverage status

Django application providing queryset sealing capability to force appropriate usage of only()/defer() and select_related()/prefetch_related().

Installation

pip install django-seal

Add 'seal' to your INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    ...
    'seal',
    ...
]

Usage

# models.py
from django.db import models
from seal.models import SealableModel

class Location(SealableModel):
    latitude = models.FloatField()
    longitude = models.FloatField()

class SeaLion(SealableModel):
    height = models.PositiveIntegerField()
    weight = models.PositiveIntegerField()
    location = models.ForeignKey(Location, models.CASCADE, null=True)
    previous_locations = models.ManyToManyField(Location, related_name='previous_visitors')

By default UnsealedAttributeAccess warnings will be raised on sealed objects attributes accesses

>>> location = Location.objects.create(latitude=51.585474, longitude=156.634331)
>>> sealion = SeaLion.objects.create(height=1, weight=100, location=location)
>>> sealion.previous_locations.add(location)
>>> SeaLion.objects.only('height').seal().get().weight
UnsealedAttributeAccess:: Attempt to fetch deferred field "weight" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().location
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().previous_locations.all()
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed <SeaLion instance>.

You can elevate the warnings to exceptions by filtering them. This is useful to assert no unsealed attribute accesses are performed when running your test suite for example.

>>> import warnings
>>> from seal.exceptions import UnsealedAttributeAccess
>>> warnings.filterwarnings('error', category=UnsealedAttributeAccess)
>>> SeaLion.objects.only('height').seal().get().weight
Traceback (most recent call last)
...
UnsealedAttributeAccess:: Attempt to fetch deferred field "weight" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().location
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().previous_locations.all()
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed <SeaLion instance>.

Or you can configure logging to capture warnings to log unsealed attribute accesses to the py.warnings logger which is a nice way to identify and address unsealed attributes accesses from production logs without taking your application down if some instances happen to slip through your battery of tests.

>>> import logging
>>> logging.captureWarnings(True)

Sealable managers can also be automatically sealed at model definition time to avoid having to call seal() systematically by passing seal=True to SealableModel subclasses, SealableManager and SealableQuerySet.as_manager.

from django.db import models
from seal.models import SealableManager, SealableModel, SealableQuerySet

class Location(SealableModel, seal=True):
    latitude = models.FloatField()
    longitude = models.FloatField()

class SeaLion(SealableModel):
    height = models.PositiveIntegerField()
    weight = models.PositiveIntegerField()
    location = models.ForeignKey(Location, models.CASCADE, null=True)
    previous_locations = models.ManyToManyField(Location, related_name='previous_visitors')

    objects = SealableManager(seal=True)
    others = SealableQuerySet.as_manager(seal=True)

Development

Make your changes, and then run tests via tox:

tox

Metadata

Release files for django-seal 1.7.1

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-seal 1.7.1
File Size Uploaded
django_seal-1.7.1.tar.gz 13.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-seal 1.7.1
File Interpreter ABI Platform
django_seal-1.7.1-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 23.6 kB

Release files / django_seal-1.7.1.tar.gz

Download URL django_seal-1.7.1.tar.gz
Size 13.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e850fbbc1023780f7dae1599839459d8e818979ceecbe9f73d4a53ccb72fadbd
BLAKE2b-256 checksum
How to use checksums
950aad6cab11f8bf4a4273578c8d9a76cac52e6c476b8f06135c7b8a29ca9316
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / django_seal-1.7.1-py2.py3-none-any.whl

Download URL django_seal-1.7.1-py2.py3-none-any.whl
Size 9.9 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
4b4670c9d0b59ffbeb5432a85cc9cc1d26ebfda1b946aa695f725c5e30f63cc3
BLAKE2b-256 checksum
How to use checksums
17e64f7aee0c942982fe4046805944c00bd33ea9f4bbd32048c6a81e762c897d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9
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