How to use placeholders outside the CMS¶
Placeholders are special model fields that django CMS uses to render user-editable content (plugins) in templates. That is, it’s the place where a user can add text, video or any other plugin to a webpage, using the same frontend editing as the CMS pages.
Placeholders can be viewed as containers for CMSPlugin
instances, and
can be used outside the CMS in custom applications using the
PlaceholderField
.
By defining one (or several) PlaceholderField
on a
custom model you can take advantage of the full power of CMSPlugin
.
Get started¶
You need to define a PlaceholderField
on the model you would like to
use:
from django.db import models
from cms.models.fields import PlaceholderField
class MyModel(models.Model):
# your fields
my_placeholder = PlaceholderField('placeholder_name')
# your methods
The PlaceholderField
has one required parameter, a string slotname
.
The slotname
is used in templates, to determine where the placeholder’s plugins should appear
in the page, and in the placeholder configuration CMS_PLACEHOLDER_CONF
, which determines
which plugins may be inserted into this placeholder.
You can also use a callable for the slotname
, as in:
from django.db import models
from cms.models.fields import PlaceholderField
def my_placeholder_slotname(instance):
return 'placeholder_name'
class MyModel(models.Model):
# your fields
my_placeholder = PlaceholderField(my_placeholder_slotname)
# your methods
Warning
For security reasons the related_name for a
PlaceholderField
may not be suppressed using
'+'
; this allows the cms to check permissions properly. Attempting to do
so will raise a ValueError
.
Note
If you add a PlaceholderField to an existing model, you’ll be able to see the placeholder in the frontend editor only after saving the relevant instance.
Admin Integration¶
Changed in version 3.0.
Your model with PlaceholderFields
can still be edited in the admin. However, any
PlaceholderFields in it will only be available for editing from the frontend.
PlaceholderFields
must not be present in any fieldsets
, fields
, form
or other
ModelAdmin
field’s definition attribute.
To provide admin support for a model with a PlaceholderField
in your application’s admin, you
need to use the mixin PlaceholderAdminMixin
along with the
ModelAdmin
. Note that the PlaceholderAdminMixin
must precede
the ModelAdmin
in the class definition:
from django.contrib import admin
from cms.admin.placeholderadmin import PlaceholderAdminMixin
from myapp.models import MyModel
class MyModelAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
I18N Placeholders¶
Out of the box PlaceholderAdminMixin
supports multiple
languages and will display language tabs. If you extend your model admin class derived from
PlaceholderAdminMixin
and overwrite change_form_template
have a look at
admin/placeholders/placeholder/change_form.html
to see how to display the language tabs.
If you need other fields translated as well, django CMS has support for django-hvad. If you use
a TranslatableModel
model be sure to not include the placeholder fields amongst the
translated fields:
class MultilingualExample1(TranslatableModel):
translations = TranslatedFields(
title=models.CharField('title', max_length=255),
description=models.CharField('description', max_length=255),
)
placeholder_1 = PlaceholderField('placeholder_1')
def __unicode__(self):
return self.title
Be sure to combine both hvad’s TranslatableAdmin
and PlaceholderAdminMixin
when
registering your model with the admin site:
from cms.admin.placeholderadmin import PlaceholderAdminMixin
from django.contrib import admin
from hvad.admin import TranslatableAdmin
from myapp.models import MultilingualExample1
class MultilingualModelAdmin(TranslatableAdmin, PlaceholderAdminMixin, admin.ModelAdmin):
pass
admin.site.register(MultilingualExample1, MultilingualModelAdmin)
Templates¶
To render the placeholder in a template you use the render_placeholder
tag from the
cms_tags
template tag library:
{% load cms_tags %}
{% render_placeholder mymodel_instance.my_placeholder "640" %}
The render_placeholder
tag takes the following parameters:
PlaceholderField
instancewidth
parameter for context sensitive plugins (optional)language
keyword pluslanguage-code
string to render content in the specified language (optional)
The view in which you render your placeholder field must return the
request
object in the context. This is
typically achieved in Django applications by using RequestContext
:
from django.shortcuts import get_object_or_404, render
def my_model_detail(request, id):
object = get_object_or_404(MyModel, id=id)
return render(request, 'my_model_detail.html', {
'object': object,
})
If you want to render plugins from a specific language, you can use the tag like this:
{% load cms_tags %}
{% render_placeholder mymodel_instance.my_placeholder language 'en' %}
Adding content to a placeholder¶
Changed in version 3.0.
Placeholders can be edited from the frontend by visiting the page displaying your model (where you
put the render_placeholder
tag), then appending ?edit
to the page’s URL.
This will make the frontend editor top banner appear (and if necessary will require you to login).
Once in frontend editing mode, the interface for your application’s PlaceholderFields
will work
in much the same way as it does for CMS Pages, with a switch for Structure and Content modes and so
on.
There is no automatic draft/live functionality for general Django models, so content is updated instantly whenever you add/edit them.
Options¶
If you need to change ?edit
to a custom string (say, ?admin_on
) you may
set CMS_TOOLBAR_URL__EDIT_ON
variable in your settings.py
to
"admin_on"
.
You may also change other URLs with similar settings:
?edit_off
(CMS_TOOLBAR_URL__EDIT_OFF
)?build
(CMS_TOOLBAR_URL__BUILD
)?toolbar_off
(CMS_TOOLBAR_URL__DISABLE
)
When changing these settings, please be careful because you might inadvertently replace reserved
strings in system (such as ?page
). We recommended you use safely unique strings for this option
(such as secret_admin
or company_name
).
Permissions¶
To be able to edit a placeholder user must be a staff
member and needs either edit permissions
on the model that contains the PlaceholderField
, or permissions for
that specific instance of that model. Required permissions for edit actions are:
to
add
: requireadd
orchange
permission on related Model or instance.to
change
: requireadd
orchange
permission on related Model or instance.to
delete
: requireadd
orchange
ordelete
permission on related Model or instance.
With this logic, an user who can change
a Model’s instance but can not add
a new
Model’s instance will be able to add some placeholders or plugins to existing Model’s instances.
Model permissions are usually added through the default Django auth
application and its admin
interface. Object-level permission can be handled by writing a custom authentication backend as
described in django docs
For example, if there is a UserProfile
model that contains a PlaceholderField
then the
custom backend can refer to a has_perm
method (on the model) that grants all rights to current
user only based on the user’s UserProfile
object:
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_staff:
return False
if isinstance(obj, UserProfile):
if user_obj.get_profile()==obj:
return True
return False