New in version 3.0.
You can extend the page and title models with your own fields (e.g. adding an icon for every page) by using the extension models: cms.extensions.PageExtension and cms.extensions.TitleExtension, respectively.
To add a field to the page model, create a class that inherits from cms.extensions.PageExtension. Make sure to import the cms.extensions.PageExtension model. Your class should live in one of your apps’ models.py (or module). Since PageExtension (and TitleExtension) inherit from django.db.models.Model, you are free to add any field you want but make sure you don’t use a unique constraint on any of your added fields because uniqueness prevents the copy mechanism of the extension from working correctly. This means that you can’t use one-to-one relations on the extension model. Finally, you’ll need to register the model with using extension_pool.
Here’s a simple example which adds an icon field to the page:
from django.db import models
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool
class IconExtension(PageExtension):
image = models.ImageField(upload_to='icons')
extension_pool.register(IconExtension)
To make your extension editable, you must first create an admin class that subclasses cms.extensions.PageExtensionAdmin. This admin handles page permissions. If you want to use your own admin class, make sure to exclude the live versions of the extensions by using filter(extended_page__publisher_is_draft=True) on the queryset.
Continuing with the example model above, here’s a simple corresponding PageExtensionAdmin class:
from django.contrib import admin
from cms.extensions import PageExtensionAdmin
from .models import IconExtension
class IconExtensionAdmin(PageExtensionAdmin):
pass
admin.site.register(IconExtension, IconExtensionAdmin)
Since PageExtensionAdmin inherits from ModelAdmin, you’ll be able to use the normal set of Django ModelAdmin properties, as appropriate to your circumstance.
Once you’ve registered your admin class, a new model will appear in the top- level admin list.
Note that the field that holds the relationship between the extension and a CMS Page is non-editable, so it will not appear in the admin views. This, unfortunately, leaves the operator without a means of “attaching” the page extension to the correct pages. The way to address this is to use a CMSToolbar.
To access a page extension in page templates you can simply access the approriate related_name field that is now available on the Page object.
As per normal Django defaul related_name naming mechanism, the appropriate field to access is the same as your PageExtension model name, but lowercased. Assuming your Page Extension model class is IconExtension, the relationship to the page extension will be available on page.iconextension, so you can use something like:
{% load staticfiles %}
{# rest of template omitted ... #}
{% if request.current_page.iconextension %}
<img src="{% static request.current_page.iconextension.url %}">
{% endif %}
Where request.current_page is the way to access the current page that is rendering the template.
It is important to remember that unless the operator has already assigned a page extension to every page, a page may not have the iconextension relationship available, hence the use of the {% if ... %}...{% endif %} above.
If your PageExtension or TitleExtension includes a ForeignKey from another model or includes a ManyToMany field, you should also override the method copy_relations(self, oldinstance, language) so that these fields are copied appropriately when the CMS makes a copy of your extension to support versioning, etc.
Here’s an example that uses a ManyToMany` field:
from django.db import models
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool
class MyPageExtension(PageExtension):
page_categories = models.ManyToMany('categories.Category', blank=True, null=True)
def copy_relations(self, oldinstance, language):
for page_category in oldinstance.page_categories.all():
page_category.pk = None
page_category.mypageextension = self
page_category.save()
extension_pool.register(MyPageExtension)