You can't always predict the shape your content will take. django-flexible-content
lets you manage rich content without sacrificing flexibility or CMS usability.
With django-flexible-content
:
- Your models can hold one or more content items (text, image, video embed)
- You can skin each type of item in the Django template language
- You can create new item types to suit your needs
Scenarios where django-flexible-content
might help you:
- A blog where CMS users need precise control over each post's content (for example, placing a tweet in the middle of the page that complies with Twitter's display requirements).
- With a Tweet item type, the user could enter a tweet's ID or URL in and display it per a standard Django template. This tweet could also appear between two giant chunks of text (other items, too).
- A site with a bunch of randomly-placed pages, even ones with a contact form, slideshow, or an introductory video.
- Your pages can be managed in the CMS, and each one of those types of custom content can be a content item type.
- You want stylistic consistency that WYSIWYG-uploaded images can't provide.
- A user uploads an image, and you generate its markup, not some JavaScript code.
Requirements:
- Your project is configured to load templates from app directories (it is by default).
- Your project uses the staticfiles app. It must also be configured to find staticfiles in app directories (it is by default).
That said, let's get started:
-
Install the package:
pip install django-flexible-content
-
Add it to your settings file.
INSTALLED_APPS = ( 'flexible_content', 'flexible_content.default_item_types', # Optional: Five basic types of content item. # other apps here )
-
Sync your database:
python manage.py syncdb
-
For each model you want to add content items to, subclass ContentArea. For example, my_project/my_app/models.py:
from django.db import models from flexible_content.models import ContentArea class BlogPost(ContentArea): title = models.CharField(max_length=50) slug = models.CharField(max_length=50) class Meta: verbose_name = "blog post"
Note that this won't change your database schema at all: ContentArea is an abstract class that just adds helper functionality.
-
For each model that subclasses ContentArea, define a custom ModelAdmin that subclasses ContentAreaAdmin. For example, my_project/my_app/admin.py:
from django.contrib import admin from flexible_content.admin import ContentAreaAdmin from .models import BlogPost class BlogPostAdmin(ContentAreaAdmin): pass admin.sites.register(BlogPost, BlogPostAdmin)
-
Run
python manage.py collectstatic
to collect all static files. -
Start your web server and go to the admin for the BlogPost model (or whichever one you added it to). Observe, flexible content controls!
Once your admin is set up, using flexible content in your templates is simple: the get_rendered_content
method on your model (the one that subclasses ContentArea
) will return all of its items as HTML. For our blog example above, you might edit my_project/templates/my_app/blog-detail.html
as follows:
<h1>{{ object.title }}</h1>
{{ object.get_rendered_content|safe }}
You can define your own templates that replace the ones included with the default_item_types
app.
-
In one of your own app's
templates
directory (or in a folder specified by theTEMPLATE_DIRS
setting), create a folder calledflexible-content
. -
Inside of that directory, create an HTML file based on the type's slug:
flexible-content/download.html flexible-content/image.html flexible-content/plain-text.html flexible-content/raw-html.html flexible-content/video.html
-
Ensure that those templates will be discovered first:
- If you placed them in an app's
templates
directory, make sure that app comes beforeflexible_content.default_item_types
in yourINSTALLED_APPS
setting. - If you placed them in an arbitrary template directory, make sure:
- That directory is specified in the
TEMPLATES_DIRS
setting. - The filesystem loader (which uses
TEMPLATE_DIRS
) comes before the app_directories loader in theTEMPLATE_LOADERS
setting.
- That directory is specified in the
- If you placed them in an app's
I'll write this documentation soon, I promise! Until then, see flexible_content_types.default_item_types.models
for examples. Once you've created those models that subclass BaseItem, you also need to specify that model in your settings:
FLEXIBLE_CONTENT = {
'ITEM_TYPES': (
'my_app.RichText',
'default_item_types.Image'
),
}