Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/charettes/django-seal
Django application providing queryset sealing capability.
https://github.com/charettes/django-seal
Last synced: 6 days ago
JSON representation
Django application providing queryset sealing capability.
- Host: GitHub
- URL: https://github.com/charettes/django-seal
- Owner: charettes
- License: mit
- Created: 2018-01-03T20:55:54.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2024-09-05T12:37:27.000Z (5 months ago)
- Last Synced: 2025-01-18T01:05:00.064Z (13 days ago)
- Language: Python
- Homepage:
- Size: 232 KB
- Stars: 253
- Watchers: 5
- Forks: 5
- Open Issues: 5
-
Metadata Files:
- Readme: README.rst
- Changelog: CHANGELOG.rst
- License: LICENSE
Awesome Lists containing this project
- stars - charettes/django-seal - Django application providing queryset sealing capability. (Python)
- stars - charettes/django-seal - Django application providing queryset sealing capability. (Python)
README
django-seal
===========.. image:: https://publicdomainvectors.org/photos/Seal2.png
:target: https://publicdomainvectors.org
:alt: Seal------------
.. image:: https://github.com/charettes/django-seal/workflows/Test/badge.svg
:target: https://github.com/charettes/django-seal/actions
:alt: Build Status.. image:: https://coveralls.io/repos/github/charettes/django-seal/badge.svg?branch=master
:target: https://coveralls.io/github/charettes/django-seal?branch=master
:alt: Coverage statusDjango application providing queryset sealing capability to force appropriate usage of ``only()``/``defer()`` and
``select_related()``/``prefetch_related()``.Installation
------------.. code:: sh
pip install django-seal
Usage
-----.. code:: python
# models.py
from django.db import models
from seal.models import SealableModelclass 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
.. code:: python
>>> 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.objects.seal().get().location
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed .
>>> SeaLion.objects.seal().get().previous_locations.all()
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed .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... code:: python
>>> 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.objects.seal().get().location
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed .
>>> SeaLion.objects.seal().get().previous_locations.all()
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed .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... code:: python
>>> import logging
>>> logging.captureWarnings(True).. _elevate the warnings to exceptions by filtering them: https://docs.python.org/3/library/warnings.html#warnings.filterwarnings
.. _configure logging to capture warnings: https://docs.python.org/3/library/logging.html#logging.captureWarningsSealable 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``... code-block:: python
from django.db import models
from seal.models import SealableManager, SealableModel, SealableQuerySetclass 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:
.. code:: sh
tox