Allows ORM constructs to be sealed to prevent them from executing queries on attribute accesses.
Project description
Django application providing queryset sealing capability to force appropriate usage of only()/defer() and select_related()/prefetch_related().
Installation
pip install django-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()
Development
Make your changes, and then run tests via tox:
tox
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.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size django_seal-1.4.0-py2.py3-none-any.whl (8.4 kB) | File type Wheel | Python version py2.py3 | Upload date | Hashes View |
Filename, size django-seal-1.4.0.tar.gz (6.8 kB) | File type Source | Python version None | Upload date | Hashes View |
Hashes for django_seal-1.4.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3746bf938d334de7eac5a388a7cc1c40c3448f71478016e062e1739dc31605e6 |
|
MD5 | bba38a47a20cb48b9e7f95c68009c834 |
|
BLAKE2-256 | be3b0c9661ed7ec26d89ae3cf7ef200c83a58de72a2bccf0c4b0631edc4a9436 |