django CMS Documentation

repository·main·Indexed 27 days ago

https://github.com/django-cms/django-cms

An open-source enterprise content management system powered by Django, featuring front-end editing, internationalization, and a flexible plugin system. Documentation covers the `cms` management CLI for installation checks, data copying, and tree repairs, as well as the `startcmsproject` command for bootstrapping new projects from templates.

Tokens
87.1K
Snippets
187
Records
525
Agent score
94%

What's inside django-cms

  1. Understand the Grouper / Content pattern

    main

    django CMS uses a split architecture for all editable entities (pages, aliases, blog posts, etc.) to handle translations and versioning efficiently. Every content object consists of two cooperating parts:

    1. Grouper: Holds the long-lived identity of the object. It represents the 'noun' (e.g., this page exists at this position in the tree). It survives translations, versions, and edits. Typical fields include site, tree position, is_home, and application_urls.
    2. Content: Holds the editable state for a specific combination of language × version. It represents the 'adjective' (e.g., this title, this template, this set of placeholders). There are many content rows per one grouper.

    This split ensures that a page's URL and position in the tree remain stable even when editors create new translations or publish new versions.

  2. Understand the components of a django CMS plugin

    main

    A django CMS plugin is a reusable content publisher that can be inserted into any placeholder. It follows a pattern similar to Django's Model-View-Template (MVT) architecture:

    ComponentFunctionSubclass
    Model (optional)Plugin instance configurationCMSPlugin
    ViewDisplay logicCMSPluginBase
    TemplateRenderingN/A

    Use a model (subclassing CMSPlugin) when your plugin needs configuration (e.g., setting a specific time range for a 'Latest Releases' box). If the plugin always performs the same action without user configuration, a model is not required.

  3. Understand the three building blocks of django CMS

    main

    A django CMS site is composed of three fundamental building blocks. Choosing the right one depends on whether you are creating a unit of editable content, a component for composition, or mounting an external application.

    1. Content Object: The unit of editable content. The most common type is a Page, which lives in the page tree, carries a URL, drives menus, and manages permissions. Other examples include Aliases (reusable content) and app-defined objects like blog posts.
    2. Plugin: The unit of composition. A reusable component that an editor can drop into a Placeholder within a content object. Each plugin instance has its own configuration and data.
    3. Apphook: The method for mounting a Django application onto the page tree. An apphook is attached to a CMS page via Advanced settings. The page provides the URL prefix, and the application manages all URLs and content objects below that prefix.
  4. Understand the django CMS role-based architecture

    main

    django CMS is designed to separate the concerns of three distinct roles, allowing them to work on their own surfaces without needing to understand the internals of the others:

    • Designers: Work in templates and CSS to define the layout vocabulary and drag-and-drop tools.
    • Developers: Work in Django (apps, models, plugins, apphooks, and configuration). Extensibility is provided via Python APIs rather than a no-code builder.
    • Editors: Work in the frontend toolbar and structure board to compose pages by adding plugins to placeholders, without editing code or templates.
  5. Understand the django CMS request lifecycle

    main

    django CMS extends the standard Django request-to-response cycle by hooking into middleware, URL resolution, and template rendering. The lifecycle follows these primary stages:

    1. Middleware Preamble: Executes CMS-specific middleware (ApphookReload, CurrentPage, Language, Toolbar).
    2. URL Resolution: Matches the URL slug against the PageUrl table to find a Page object.
    3. Language Determination: Resolves the active language via Django's LocaleMiddleware (URL prefix, session, cookie, or headers).
    4. Content Resolution: Determines the correct PageContent row based on the resolved Page and language (including fallback logic).
    5. Page Cache Gate: Checks if a full-page cached response exists to avoid rendering.
    6. Template Selection: Uses PageContent.template to select the Django template.
    7. Placeholder Rendering: Renders plugins within {% placeholder %} tags.
    8. Menu Building: Builds navigation if {% show_menu %} is used.
    9. Response: Returns the final response to the browser.

    This lifecycle is useful for debugging missing pages, cache invalidation issues, or understanding how content is served.

  6. Understand the django CMS publishing model

    main

    In django CMS, publishing is not a core feature but a contract that versioning packages implement.

    Without a versioning package:

    • There is no distinction between 'draft' and 'published'.
    • Editing a PageContent row immediately makes changes visible.
    • There is only one PageContent row per language.
    • PageContent.objects and PageContent.admin_manager return the same results.

    With djangocms-versioning (the standard package):

    • Multiple content rows per language are allowed (one for each draft/version).
    • Content rows have states: Draft, Published, Unpublished, or Archived.
    • PageContent.objects is filtered to return only the published row per language.
    • PageContent.admin_manager acts as an escape hatch to return every row regardless of state.
  7. Understand the django CMS multilingual content model

    main

    django CMS uses a 'grouper/content' split to manage multilingualism.

    • Grouper (Page, Alias): Language-agnostic. It manages identity, tree position, and apphook bindings.
    • Content (PageContent, AliasContent): Per-language. Each translation is a new content row for the same grouper.

    Because content is per-language, each translation has its own:

    • Placeholders and plugins
    • title and meta_description
    • template choice
    • in_navigation setting
    • Slugs (managed via PageUrl rows keyed by (page, language))
  8. Identify the core features of django CMS

    main

    The django CMS core is kept small and stable, focusing on a limited set of responsibilities:

    • Managing pages and their hierarchical structure.
    • Exposing placeholders for content objects to publish into.
    • Coordinating plugins and apphooks to allow other Django apps to integrate.
    • Integrating editing capabilities directly into rendered pages.

    Advanced features like versioning, alias content, headless rendering, the rich-text editor, and the frontend admin theme are provided via separate packages.

  9. Understand Application Hooks (apphooks)

    main

    An Application Hook (or apphook) attaches a Django application's URL tree to a django CMS page, turning that page into a mount point.

    When an apphook is attached to a CMS page (e.g., /records/), the CMS page provides the base path, and the attached application provides the remainder of the URL space (e.g., /records/1984/).

    Key Characteristics:

    • URL Routing: Requests to the base path and everything below it are routed into the hooked application instead of being served as normal CMS page content.
    • CMS Integration: Unlike adding URLs directly to urls.py, apphooks make the CMS aware of the URL space. This prevents slug conflicts, allows for menu integration, and enables the use of CMS publishing workflows.
    • Publishing Requirement: An apphook only serves public traffic once the associated CMS page (and its parent pages) are published.
  10. Update Apphook usage for version 3.0

    main

    Apphooks have moved from the title to the page model. Key changes include:

    • Single Language per Apphook: You can no longer have separate apphooks for each language.
    • Namespace Requirement: If you use apphook apps with app_name for app namespaces, you must now fill out the application instance name field on the page.
    • request.current_app Removal: This attribute has been removed. To retrieve the current app namespace in a view, use resolve(request.path_info).namespace.
  11. Attach an application multiple times using app_name

    main

    To attach the same application to multiple CMS pages (multiple mount points), the class defining your apphook must include an app_name attribute. This attribute serves as the fallback namespace for URL reversing and provides a default value for the Application instance name field in the CMS admin.

    When using reverse('myapp:index') or {% url 'myapp:index' %} in your views or templates, ensure app_name matches the namespace used in your URL reversing. If the Application instance name set in the CMS admin does not match, django CMS will fall back to the app_name defined in the class, preventing NoReverseMatch errors.

    class MyApphook(CMSApp):
        name = _("My Apphook")
        app_name = "myapp"
    
        def get_urls(self, page=None, language=None, **kwargs):
            return ["myapp.urls"]
  12. Register a model for frontend editing via CMSAppConfig

    main

    Since django CMS 4, you must register models for frontend editing by adding a CMSAppConfig class to your app's cms_config.py file. Set cms_enabled = True and define cms_toolbar_enabled_models, which is a list of tuples containing the model class and the view responsible for rendering it. If using Class-Based Views (CBVs), use the stub view (the endpoint view) in the tuple.

    from cms.app_base import CMSAppConfig
    from . import models, views
    
    
    class MyAppConfig(CMSAppConfig):
        cms_enabled = True
        # For function-based views
        cms_toolbar_enabled_models = [(models.MyModel, views.render_my_model)]
    
        # For class-based views, use the endpoint view
        # cms_toolbar_enabled_models = [(models.MyModel, views.my_model_endpoint_view)]