Skip to main content

A flexible, scalable CMS with custom node types, and flexible block content.

Project description

https://img.shields.io/travis/django-fluent/django-fluent-pages/master.svg?branch=master https://img.shields.io/pypi/v/django-fluent-pages.svg https://img.shields.io/pypi/l/django-fluent-pages.svg https://img.shields.io/codecov/c/github/django-fluent/django-fluent-pages/master.svg

django-fluent-pages

This is a stand-alone module, which provides a flexible, scalable CMS with custom node types, and flexible block content.

Features:

  • A fully customizable page hierarchy.

  • Support for multilingual websites.

  • Support for multiple websites in a single database.

  • Fast SEO-friendly page URLs.

  • SEO optimized (meta keywords, description, title, 301-redirects, sitemaps integration).

  • Plugin support for custom page types, which:

  • Integrate application logic in page trees.

  • Integrate advanced block editing (via as django-fluent-contents).

For more details, see the documentation at Read The Docs.

Page tree customization

This module provides a page tree, where each node type can be a different model. This allows developers like yourself to structure your site tree as you see fit. For example:

  • Build a tree structure of RST pages, by defining a RstPage type.

  • Build a tree with widget-based pages, by integrating django-fluent-contents.

  • Build a “product page”, which exposes all products as sub nodes.

  • Build a tree of a homepage, subsection, and article node, each with custom fields like professional CMSes have.

Each node type can have it’s own custom fields, attributes and rendering.

In case you’re building a custom CMS, this module might just be suited for you, since it provides the tree for you, without bothering with anything else. The actual page contents is defined via page type plugins.

Installation

First install the module, preferably in a virtual environment:

pip install django-fluent-pages

All dependencies will be automatically installed.

Configuration

You can also use the ready-made template:

mkdir my-website.com
cd my-website.com
django-admin.py startproject mywebsite . -e py,rst,example,gitignore --template=https://github.com/edoburu/django-project-template/archive/django-fluent.zip

Or create a new project:

cd ..
django-admin.py startproject fluentdemo

To have a standard setup with django-fluent-contents integrated, use:

INSTALLED_APPS += (
    # The CMS apps
    'fluent_pages',

    # Required dependencies
    'mptt',
    'parler',
    'polymorphic',
    'polymorphic_tree',
    'slug_preview',

    # Optional widget pages via django-fluent-contents
    'fluent_pages.pagetypes.fluentpage',
    'fluent_contents',
    'fluent_contents.plugins.text',
    'django_wysiwyg',

    # Optional other CMS page types
    'fluent_pages.pagetypes.redirectnode',

    # enable the admin
    'django.contrib.admin',
)

DJANGO_WYSIWYG_FLAVOR = "yui_advanced"

Note each CMS application is optional. Only fluent_pages and mptt are required. The remaining apps add additional functionality to the system.

In urls.py:

urlpatterns += patterns('',
    url(r'', include('fluent_pages.urls'))
)

The database can be created afterwards:

./manage.py migrate
./manage.py runserver

Custom page types

The key feature of this module is the support for custom node types. Take a look in the existing types at fluent_pages.pagetypes to see how it’s being done.

It boils down to creating a package with 2 files:

The models.py file should define the custom node type, and any fields it has:

from django.db import models
from django.utils.translation import ugettext_lazy as _
from fluent_pages.models import HtmlPage
from mysite.settings import RST_TEMPLATE_CHOICES


class RstPage(HtmlPage):
    """
    A page that renders RST code.
    """
    rst_content = models.TextField(_("RST contents"))
    template = models.CharField(_("Template"), max_length=200, choices=RST_TEMPLATE_CHOICES)

    class Meta:
        verbose_name = _("RST page")
        verbose_name_plural = _("RST pages")

A page_type_plugins.py file that defines the metadata, and rendering:

from fluent_pages.extensions import PageTypePlugin, page_type_pool
from .models import RstPage


@page_type_pool.register
class RstPagePlugin(PageTypePlugin):
    model = RstPage
    sort_priority = 10

    def get_render_template(self, request, rstpage, **kwargs):
        return rstpage.template

A template could look like:

{% extends "base.html" %}
{% load markup %}

{% block headtitle %}{{ page.title }}{% endblock %}

{% block main %}
  <h1>{{ page.title }}</h1>

  <div id="content">
    {{ page.rst_content|restructuredtext }}
  </div>
{% endblock %}

Et, voila: with very little code a custom CMS was just created.

Optionally, a model_admin can also be defined, to have custom field layouts or extra functionality in the edit or delete page.

Plugin configuration

The plugin can define the following attributes:

  • model - the model for the page type

  • model_admin - the custom admin to use (must inherit from PageAdmin)

  • render_template - the template to use for rendering

  • response_class - the response class (by default TemplateResponse)

  • is_file - whether the node represents a file, and shouldn’t end with a slash.

  • can_have_children - whether the node type is allowed to have child nodes.

  • urls - a custom set of URL patterns for sub pages (either a module name, or patterns() result).

  • sort_priority - a sorting order in the “add page” dialog.

It can also override the following functions:

  • get_response(self, request, page, **kwargs) - completely redefine the response, instead of using response_class, render_template, etc..

  • get_render_template(self, request, page, **kwargs) - return the template to render, by default this is render_template.

  • get_context(self, request, page, **kwargs) - return the template context for the node.

Details about these attributes is explained in the documentation.

Application nodes

As briefly mentioned above, a page type can have it’s own set of URL patterns, via the urls attribute. This allows implementing page types such as a “product page” in the tree, which automatically has all products from the database as sub pages. The provides example module demonstrates this concept.

The URL patterns start at the full path of the page, so it works similar to a regular include() in the URLconf. However, a page type may be added multiple times to the tree. To resolve the URLs, there are 2 functions available:

  • fluent_pages.urlresolvers.app_reverse() - this reverse() like function locates a view attached to a page.

  • fluent_pages.urlresolvers.mixed_reverse() - this resolver tries app_reverse() first, and falls back to the standard reverse().

The mixed_reverse() is useful for third party applications which can operate either stand-alone (mounted in the normal URLconf), or operate as page type node in combination with django-fluent-pages. These features are also used by django-fluent-blogs to provide a “Blog” page type that can be added to a random point of the tree.

Adding pages to the sitemap

Optionally, the pages can be included in the sitemap. Add the following in urls.py:

from fluent_pages.sitemaps import PageSitemap

sitemaps = {
    'pages': PageSitemap,
}

urlpatterns += patterns('',
    url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
)

Contributing

This module is designed to be generic. In case there is anything you didn’t like about it, or think it’s not flexible enough, please let us know. We’d love to improve it!

If you have any other valuable contribution, suggestion or idea, please let us know as well because we will look into it. Pull requests are welcome too. :-)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-fluent-pages-1.1.4.tar.gz (346.6 kB view details)

Uploaded Source

Built Distribution

django_fluent_pages-1.1.4-py2.py3-none-any.whl (143.5 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-fluent-pages-1.1.4.tar.gz.

File metadata

File hashes

Hashes for django-fluent-pages-1.1.4.tar.gz
Algorithm Hash digest
SHA256 fcecb45438be3576179427134f28c089366614a1c8522cbd2486d41e40db3417
MD5 e2dbd42d3d93709ae81b22c278c1f970
BLAKE2b-256 ee746ec0937f47be1402bd6e609e36cc061bc0c03078d86fc0dbaeb92bbdd837

See more details on using hashes here.

File details

Details for the file django_fluent_pages-1.1.4-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for django_fluent_pages-1.1.4-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 6b5915ecc4b570095702976f2ba3c7f302af8bd2a5426da58804314bcd11d158
MD5 daa6c50818dc5cdad188295af6bc310c
BLAKE2b-256 2ebe953b089b33a3d5b31e77f62610b05f2eb8b26b7e0bc4ffd94ced5fc529a7

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page