Control public visibility of model instances.
Project description
Django Published
Published allows you to control the public visibility of model instances. Useful in situations like below!
You have a model where some number of instances of the model should
be "live". A good example of this would be an Article model, where
you've written some articles that are "live", some that might've
been taken down, some that are still "in progress", and others that
are ready to "go live", but have a "go live" date that's in the
future.
This project is based on django-model-gatekeeper by WGBH.
Quick start
- Add "published" to your
INSTALLED_APPS
:
INSTALLED_APPS = [
...
'published',
]
Gatekeeping Models
The main use for django-published is where you have a model with many instances, but you only want some to be "live" on the site.
A good example is a generic "Article" model:
- Some articles are ready-to-go and you want them live to the public;
- Other articles are still being worked on - you want to be able to preview them, but not take them live JUST yet;
- Some articles might be pulled (and re-published later)
- Some articles are ready to be published, but you want them to only go live at a later date.
To start using this, all you need to do is subclass the
PublishedAbstractModel
abstract class,
e.g.:
from published.models import PublishedAbstractModel
class Article(PublishedAbstractModel):
...
The superclass creates two fields:
-
publish_status
- this has 3 possible values:- NEVER_AVAILABLE = "permanently off" - hard-wired to NEVER be available to the public
- AVAILABLE_AFTER = "use live_as_of" date to determine if the object is available to the public
- AVAILABLE = "always on" - hard-wired to be always available to the public
-
live_as_of
- this is the timestamp of when the object should go live, if publish_status is AVAILABLE_AFTER
You set the publish_status
and live_as_of
values through the admin.
Generic Model Views
Setting up django-published for generic models views is easy!
Using the Article model as an example, here is the corresponding view code for listing and detail views.
from django.views.generic import DetailView, ListView
from .models import Article
from published.mixins import PublishedListMixin, PublishedDetailMixin
class ArticleListView(PublishedListMixin, ListView):
model = Article
template_name = 'article/article_list.html'
context_object_name = 'articles'
class ArticleDetailView(PublishedDetailMixin, DetailView):
model = Article
template_name = 'article/article_detail.html'
context_object_name = 'article'
What's happening behind the scenes:
-
In the ListView, django-published is filtering the model with the following rules:
- If the current user has admin access, always include the model instance.
- If
publish_status = AVAILABLE
, include the model instance. - If
publish_status = NEVER_AVAILABLE
, DO NOT the model instance. - If
publish_status = AVAILABLE_AFTER
, and the current date/time is afterlive_as_of
, include the model instance. - Return the filtered list of model instances.
-
In the DetailView, django-published follows the same rules but will throw a 404 error if the model instance is not available.
Custom Code
Say there's a section on your homepage that gives a list of the three most recent articles. If you just create a queryset along the lines of:
most_recent_articles = Article.objects.order_by(-date_created)[:3]
it will include articles regardless of what their gatekeeping situation is.
So there is a helper function to apply the gatekeeping rules to any queryset you generate.
queryset_filter
This takes a queryset, applies the rules and returns a filtered queryset.
from published.utils import queryset_filter
...
recent_articles = Article.objects.order_by('-date_created')
recent_articles = queryset_filter(recent_articles, is_auth)
...
By default, queryset_filter
does not apply the same exceptions as the view
mixins above. This means that unpublished model instances will be not displayed
if the current user has admin access.
The optional user
parameter allows you to enable this special case, as seen below.
queryset_filter(queryset, user=self.request.user)
available_to_public
Note: This should only be used in templates
If you need to check if an object is considered "available" in a Django template, you can use the
available_to_public
model attribute, as below.
{% for article in article_list %}
{% if article.available_to_public %}
I'm published!
{% endif %}
{% endfor %}
The Admin Interface
django-published has several helper functions to customize the admin (it
doesn't have the admin methods because there's no way to know if there
are other ModelAdmins being used, and Python's MRO doesn't allow for
chaining). All of them are in the gatekeeper.admin_helpers
file.
Readonly Fields
To use any of the below functions, one field needs to be added to the admin instance.
This can be done using add_to_readonly_fields
- A
show_publish_status
that takes thelive_as_of
andpublish_status
fields and creates a human-friendly string from them
Example code:
from published.admin import PublishedAdmin, add_to_readonly_fields
class MyModelAdmin(PublishedAdmin):
readonly_fields = ['my_field_1', 'my_field_2'] + add_to_readonly_fields()
List Display
To show the status in an admin list view, show_publish_status
needs to be added to
list_display
This can be added automatically with the add_to_list_display
method, e.g.:
from published.admin import PublishedAdmin, add_to_list_display
class MyModelAdmin(PublishedAdmin):
list_display = ['pk', 'title', ] + add_to_list_display()
Fieldsets
There are two ways to include the gatekeeper fields using the
add_to_fieldsets
method:
As a separate section
There's a section
attribute (default:
True) that returns the entire section tuple with the gatekeeper fields.
There's also a collapse
attribute
(default: False) that uses the Django Admin "collapse" class.
from published.admin import PublishedAdmin, add_to_fieldsets
class MyModelAdmin(PublishedAdmin):
fieldsets = (
(None, ...),
add_to_fieldsets(section=True, collapse=False)
)
Included as part of a section
Or you can include them as part of another section; in this case you'd
set section=False
from published.admin import PublishedAdmin, add_to_fieldsets
class MyModelAdmin(PublishedAdmin):
fieldsets = (
(None, {
'fields': (
(some set of fields),
add_to_fieldsets(section=False)
)
}),
And of course you can just do it all manually with the editable live_as_of
, publish_status
fields and the readonly
show_publish_status
field.
License
This software is released under the MIT license.
Copyright (c) 2019 WGBH Educational Foundation
Copyright (c) 2019 Luke Rogers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
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
File details
Details for the file django-published-0.5.0.tar.gz
.
File metadata
- Download URL: django-published-0.5.0.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.39.0 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4a859533fc4513bc24827edda639cf2c80913ded7b2c347017f76d136477dbda |
|
MD5 | eec88332ca536681760712cc921b66f6 |
|
BLAKE2b-256 | 254bb2ddda0d51696f4a2efd94a653e41440a2b38f19de0e42a33a8032830132 |