Handle django models drafts and published states
Project description
Django-brouillons
Handle "draft" and "public" versions of your models in Django ORM.
This module is still in a WIP version and should not be used in production if you don't know what you're doing. This modules aims to handle with a quite complex subject that requires that you add unit tests to your project to be absolutely sure that it does what you're expect in your specific cases. For now, we're aware that the module doesn't covers all of the cases of duplications of models tree, but we're hopping to increase them over the time.
It uses django-clone on the inside to duplicates django ORM models.
We recommend that you start with understanding how django-clone
works before diving into django-brouillons
.
How it is working ?
Django-brouillons
duplicates objects of a given model that aims to be moderated in two versions public
and draft
.
The draft
version can then be published so that its values are updated in the public
version.
Contributing
Feel free to send feedbacks on the module using it's Home page.
See CONTRIBUTING.md for contributions.
Install
-
Install the module from PyPI:
python3 -m pip install django-brouillons
Or, if you're using poetry :
poetry add django-brouillons
-
Add it in your
INSTALLED_APPS
:"django_brouillons",
Config
In your models
-
To handle
draft
andpublic
status in a django model, inherit from theDraftModel
class:from django_brouillons.models import DraftModel class DraftableObject(DraftModel): ...
-
Then you need to configure the django-clone settings for the model, and that will describe what strategy should be adopted regarding model related fields (for
Many to many
,ForeignKey
,OneToOne
, ...)from django_brouillons.models import DraftModel class DraftableObject(DraftModel): _clone_m2o_or_o2m_fields = ["draftable_object_many_to_many2_through"] _clone_linked_m2m_fields = ["many_to_many_objects"] ... many_to_many_objects = models.ManyToManyField("DraftableObjectManyToMany") many_to_many_2_objects_through = models.ManyToManyField( "DraftableObjectManyToMany2", through="DraftableObjectManyToMany2Through", through_fields=("draftable_object", "draftable_object_many_to_many_2"), )
As an example, you can have a look at the test app models.
In this example, the following will be applied:
many_to_many_objects
field : Them2m
fields will reference the same related objects without duplicated the related objectsdraftable_object_many_to_many2_through
field : The related objects of the table designed asdraftable_object_many_to_many2_through
related name will be duplicated
-
If your model contains some
CharFields
fields havingunique=True
they must be prefixed in theDraft
version of the model, so that they remains unique betweenPublic
andDraft
versions.This can be done filling the
_draft_prefixed_fields
attribute's of your model inheriting from theDraftModel
abstract model :from django_brouillons.models import DraftModel class DraftableObject(DraftModel): _clone_m2o_or_o2m_fields = ["draftable_object_many_to_many2_through"] _clone_linked_m2m_fields = ["many_to_many_objects"] _draft_prefixed_fields = ["slug"] slug = models.SlugField(max_length=255, unique=True)
In this example, the DraftableObject
contains a field slug
that's unique.
Listing it in the _draft_prefixed_fields
attribute indicates django-brouillons
that the value must be prefixed with the value of the _draft_prefix
attribute upon duplication in a draft
.
In the admin
Django-brouillon provides admin integrations.
-
Model admin can inherit from the
DraftModelAdminMixin
or theDraftModelAdmin
:from django_brouillons.admin import DraftModelAdminMixin @admin.register(DraftableObject) # Must be referenced to allow autocomplete class DraftableObjectAdmin( DraftModelAdmin ): pass
Doing so, several buttons will be added to your admin model change's view :
- Navigate between the
Public
andDraft
versions of the objects in the admin - Publish a
draft
version of an object into apublic
version - Create a
draft
version of an object having only apublic
- Navigate between the
-
The
DraftModelAdminMixin
contains aPublishedChangesListFilter
filter in itslist_filter
attribute that adds the the capability to filter objects having unpublished changes or not.This filter can manually be set in the
list_filter
if needed :from django_brouillons.admin import DraftModelAdminMixin, PublishedChangesListFilter @admin.register(DraftableObject) # Must be referenced to allow autocomplete class DraftableObjectAdmin( DraftModelAdmin ): list_filter = (PublishedChangesListFilter,)
Model API
Django-brouillons provides the following in it's model attributes :
DraftableObject.is_public
: Indicates if the current instance is publicDraftableObject.is_draft
: Indicates if the current instance is draftDraftableObject.has_public_version
: Indicates if the current instance has a public versionDraftableObject.has_draft_version
: Indicates if the current instance has a draft versionDraftableObject.has_unpublished_changes
: Indicates if the current instance has pending unpublished changesDraftableObject.create_draft()
: Creates a draft from a public versionDraftableObject.publish_draft()
: Publish changes of a draft version in a public version :- Creates and returns a new
public_version
if didn't exists - Updates and returns the
public_version
if already exists
- Creates and returns a new
Tests
Tests are located in the tests
packages.
Tests are written with pytest. They are based on a testapp models :
To run the tests, you must launch the command ./launch_tests.sh
A coverage report can be generated using the command ./run_coverage.sh
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.
Source Distribution
Built Distribution
Hashes for django_brouillons-0.0.4-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6e147363af59c0ee908db910f9ceace04c1ac38c61e1b5c95655e7b1f3275494 |
|
MD5 | 8bdadd5a185fa67c451e127a8a2124a6 |
|
BLAKE2b-256 | a27bbe2233eac1c0e00c2c443d42c6964a7ac3d5331beb541dab9096dfabaa0f |