Table of Contents¶
Django Deletion Side Effects Documentation¶
Django Deletion Side Effects provides a framework for gathering side effects of deleting objects in Django.
For example, imagine your website has an interface to delete users. When deleting a user in your app, it will also delete any memberships to groups along with any API credentials of that user. This information would be useful to display before the user is deleted from the website. Django Deletion Side Effects allows you to easily populate this information across your project as it grows.
Setting Up A Side Effect Handler¶
Similar to registering a signal handler, this package allows you to set up deletion handlers and register them. Each deletion side effect class must define the following:
- A deleted_obj_class variable. This variable denotes the class of the object being deleted.
- A get_side_effects method. This method is passed a list of objects of deleted_obj_class type that are candidates for deletion. The method returns a tuple of objects that are affected by deletion of the objects for deletion (i.e the side effect objects) and a list of objects that will be cascade deleted if the candidate objects are deleted.
- A get_side_effect_message method. This method is passed all of the side effect objects from gathering side effects with the class. The method is responsible for returning a human-readable string of the side effects.
A side effect handler can best be illustrated with an example. Assume we have the following models:
class GroupType(models.Model):
name = CharField(max_length=64)
class Group(models.Model):
group_type = models.ForeignKey(GroupType)
name = CharField(max_length=64)
In this case, a Group will be cascade deleted with the deletion of a GroupType. To set up a side effect for this, do the following:
from deletion_side_effects import register_deletion_side_effects, BaseDeletionSideEffects
class CascadeGroupDeletionSideEffect(BaseDeletionSideEffect):
deleted_obj_class = GroupType
def get_side_effects(self, deleted_objs):
"""
Given a list of deleted group types, return the list of side effect objects
and the list of objects that will be deleted as a result. In this case, the lists are the same.
"""
deleted_groups = Group.objects.filter(group_type__in=deleted_objs)
return deleted_groups, deleted_groups
def get_side_effect_message(self, side_effect_objs):
"""
Prints out the message about groups being deleted.
"""
return u'{0} group{1} will be deleted'.format(len(side_effect_objs), 's' if len(side_effect_objs) > 1 else '')
# Register the side effect. Note that this is best called in the App Config's ready() method
register_deletion_side_effects(CascadeGroupDeletionSideEffect)
In the above example, the side effect class inherits BaseDeletionSideEffects. The side effect handler is registered with the register_deletion_side_effects function. Note that the side effect handlers will need to be connected in the app config’s ready method for your app with side effects.
Gathering Side Effects¶
In order to gather side effects for a list of deleted objects of the same type, do the following:
from deletion_side_effects import gather_deletion_side_effects
# Find all of the side effects of deleting all group types
side_effects = gather_deletion_side_effects(GroupType, GroupType.objects.all())
print side_effects
[{
'msg': u'2 groups will be deleted',
'side_effect_objs': [
<Group: group1>,
<Group: group2>
]
}]
This case follows with using the models defined in the example above. In this example, we retrieve the side effects of deleting every group type by passing the GroupType model and the iterable of all group types to gather_deletion_side_effects. The return value of the function has a list of all side effects. Each side effect is a dictionary that has a msg field for the side effect message. It also has a list of side effect objects related to the message in the side_effect_objs field.
Installation¶
To install the latest release, type:
pip install django-deletion-side-effects
To install the latest code directly from source, type:
pip install git+git://github.com/ambitioninc/django-deletion-side-effects.git
Code documentation¶
deletion_side_effects¶
-
class
deletion_side_effects.deletion_side_effects.
BaseDeletionSideEffects
¶ Provides the interface for a user to make a deletion side effects class. The user must define the following:
- A deleted_obj_class variable. This variable denotes the class of the object being deleted.
- A ‘get_side_effects` method. This method is passed a list of objects of deleted_obj_class type that are candidates for deletion. The method returns a tuple of objects that are affected by deletion of the objects for deletion (i.e the side effect objects) and a list of objects that will be cascade deleted if the candidate objects are deleted.
- A get_side_effect_message method. This method is passed all of the side effect objects from gathering side effects with the class. The method is responsible for returning a human-readable string of he side effects.
-
get_side_effect_message
(side_effect_objects)¶ Given a list of objects that have this side effect associated with them, return a human readable message about the side effect.
-
get_side_effects
(deleted_objects)¶ Returns a tuple. The first part of the tuple is list of objects that have side effects associated with them. The second part of the tuple is a list of other objects that will be deleted as a result of the passed objects being deleted. Side effects of other deleted models will be populated when gather_deletion_side_effects is called.
-
deletion_side_effects.deletion_side_effects.
gather_deletion_side_effects
(obj_class, objs)¶ Given an object, gather the side effects of deleting it. The return value is a list of dictionaries, each of which contain the following keys:
- msg - This key contains a human-readable message of the side effect.
- side_effect_objs: This key contains a list of ever object related to this side effect and the message.
-
deletion_side_effects.deletion_side_effects.
register_deletion_side_effects
(*deletion_side_effects_handlers)¶ Registers deletion side effect handler classes. The class must inherit BaseDeletionSideEffects and define a deleted_obj_class variable.
Contributing¶
Contributions and issues are most welcome! All issues and pull requests are handled through github on the ambitioninc repository. Also, please check for any existing issues before filing a new one. If you have a great idea but it involves big changes, please file a ticket before making a pull request! We want to make sure you don’t spend your time coding something that might not fit the scope of the project.
Running the tests¶
To get the source source code and run the unit tests, run:
git clone git://github.com/ambitioninc/django-deletion-side-effects.git
cd django-deletion-side-effects
virtualenv env
. env/bin/activate
python setup.py install
coverage run setup.py test
coverage report --fail-under=100
While 100% code coverage does not make a library bug-free, it significantly reduces the number of easily caught bugs! Please make sure coverage is at 100% before submitting a pull request!
Code Styling¶
Please arrange imports with the following style
# Standard library imports
import os
# Third party package imports
from mock import patch
from django.conf import settings
# Local package imports
from deletion_side_effects.version import __version__
Please follow Google’s python style guide wherever possible.
Building the docs¶
When in the project directory:
pip install -r requirements/docs.txt
python setup.py build_sphinx
open docs/_build/html/index.html
Release Checklist¶
Before a new release, please go through the following checklist:
Bump version in deletion_side_effects/version.py
Add a release note in docs/release_notes.rst
Git tag the version
Upload to pypi:
pip install wheel python setup.py sdist bdist_wheel upload
Uploading to pypi can be accomplished by running python publish.py
Vulnerability Reporting¶
For any security issues, please do NOT file an issue or pull request on github! Please contact security@ambition.com with the GPG key provided on Ambition’s website.