django-fluent-pages


Namedjango-fluent-pages JSON
Version 3.0.2 PyPI version JSON
download
home_pagehttps://github.com/edoburu/django-fluent-pages
SummaryA flexible, scalable CMS with custom node types, and flexible block content.
upload_time2023-10-16 12:12:02
maintainer
docs_urlNone
authorDiederik van der Boor
requires_python
licenseApache 2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            *This project has reached the end of its development as CMS framework.*
*It only receives low maintenance to continue running existing websites.*
*Feel free to browse the code, but please use other Django-based CMS frameworks such as*
`Wagtail CMS <https://wagtail.io/>`_ *when you start a new project.*

django-fluent-pages
===================

.. image:: http://unmaintained.tech/badge.svg
    :target: http://unmaintained.tech
    :alt: No Maintenance Intended
.. image:: https://github.com/django-fluent/django-fluent-pages/actions/workflows/tests.yaml/badge.svg?branch=master
    :target: https://github.com/django-fluent/django-fluent-pages/actions/workflows/tests.yaml
.. image:: https://img.shields.io/pypi/v/django-fluent-pages.svg
    :target: https://pypi.python.org/pypi/django-fluent-pages/
.. image:: https://img.shields.io/pypi/l/django-fluent-pages.svg
    :target: https://pypi.python.org/pypi/django-fluent-pages/
.. image:: https://img.shields.io/codecov/c/github/django-fluent/django-fluent-pages/master.svg
    :target: https://codecov.io/github/django-fluent/django-fluent-pages?branch=master
.. image:: https://readthedocs.org/projects/django-fluent-pages/badge/?version=latest
    :target: https://django-fluent-pages.readthedocs.io/en/latest/


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:

.. code-block:: bash

    pip install django-fluent-pages

All dependencies will be automatically installed.

Configuration
-------------

You can also use the ready-made template:

.. code-block:: bash

    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:

.. code-block:: bash

    cd ..
    django-admin.py startproject fluentdemo

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

.. code-block:: python

    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``:

.. code-block:: python

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

The database can be created afterwards:

.. code-block:: bash

    ./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:

.. code-block:: python

    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:

.. code-block:: python

    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:

.. code-block:: html+django

    {% 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``:

.. code-block:: python

    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. :-)


.. _documentation: https://django-fluent-pages.readthedocs.io/
.. _django.contrib.sites: https://docs.djangoproject.com/en/dev/ref/contrib/sites/
.. _django.contrib.sitemaps: https://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/

.. _django-fluent-blogs: https://github.com/django-fluent/django-fluent-blogs
.. _django-fluent-contents: https://github.com/django-fluent/django-fluent-contents
.. _django-mptt: https://github.com/django-mptt/django-mptt
.. _django-parler: https://github.com/edoburu/django-parler
.. _django-polymorphic: https://github.com/django-polymorphic/django-polymorphic
.. _django-polymorphic-tree: https://github.com/django-polymorphic/django-polymorphic-tree


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/edoburu/django-fluent-pages",
    "name": "django-fluent-pages",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Diederik van der Boor",
    "author_email": "opensource@edoburu.nl",
    "download_url": "https://files.pythonhosted.org/packages/05/3e/38bcc549f495c2bf723065c0a55bd4e5905cfe1667c03a3ae88bccbdfc9f/django-fluent-pages-3.0.2.tar.gz",
    "platform": null,
    "description": "*This project has reached the end of its development as CMS framework.*\n*It only receives low maintenance to continue running existing websites.*\n*Feel free to browse the code, but please use other Django-based CMS frameworks such as*\n`Wagtail CMS <https://wagtail.io/>`_ *when you start a new project.*\n\ndjango-fluent-pages\n===================\n\n.. image:: http://unmaintained.tech/badge.svg\n    :target: http://unmaintained.tech\n    :alt: No Maintenance Intended\n.. image:: https://github.com/django-fluent/django-fluent-pages/actions/workflows/tests.yaml/badge.svg?branch=master\n    :target: https://github.com/django-fluent/django-fluent-pages/actions/workflows/tests.yaml\n.. image:: https://img.shields.io/pypi/v/django-fluent-pages.svg\n    :target: https://pypi.python.org/pypi/django-fluent-pages/\n.. image:: https://img.shields.io/pypi/l/django-fluent-pages.svg\n    :target: https://pypi.python.org/pypi/django-fluent-pages/\n.. image:: https://img.shields.io/codecov/c/github/django-fluent/django-fluent-pages/master.svg\n    :target: https://codecov.io/github/django-fluent/django-fluent-pages?branch=master\n.. image:: https://readthedocs.org/projects/django-fluent-pages/badge/?version=latest\n    :target: https://django-fluent-pages.readthedocs.io/en/latest/\n\n\nThis is a stand-alone module, which provides a flexible,\nscalable CMS with custom node types, and flexible block content.\n\nFeatures:\n\n* A fully customizable page hierarchy.\n* Support for multilingual websites.\n* Support for multiple websites in a single database.\n* Fast SEO-friendly page URLs.\n* SEO optimized (meta keywords, description, title, 301-redirects, sitemaps integration).\n* Plugin support for custom page types, which:\n\n * Integrate application logic in page trees.\n * Integrate advanced block editing (via as django-fluent-contents_).\n\nFor more details, see the documentation_ at Read The Docs.\n\nPage tree customization\n-----------------------\n\nThis module provides a page tree, where each node type can be a different model.\nThis allows developers like yourself to structure your site tree as you see fit. For example:\n\n* Build a tree structure of RST pages, by defining a ``RstPage`` type.\n* Build a tree with widget-based pages, by integrating django-fluent-contents_.\n* Build a \"product page\", which exposes all products as sub nodes.\n* Build a tree of a *homepage*, *subsection*, and *article* node, each with custom fields like professional CMSes have.\n\nEach node type can have it's own custom fields, attributes and rendering.\n\nIn case you're building a custom CMS, this module might just be suited for you,\nsince it provides the tree for you, without bothering with anything else.\nThe actual page contents is defined via page type plugins.\n\n\nInstallation\n============\n\nFirst install the module, preferably in a virtual environment:\n\n.. code-block:: bash\n\n    pip install django-fluent-pages\n\nAll dependencies will be automatically installed.\n\nConfiguration\n-------------\n\nYou can also use the ready-made template:\n\n.. code-block:: bash\n\n    mkdir my-website.com\n    cd my-website.com\n    django-admin.py startproject mywebsite . -e py,rst,example,gitignore --template=https://github.com/edoburu/django-project-template/archive/django-fluent.zip\n\nOr create a new project:\n\n.. code-block:: bash\n\n    cd ..\n    django-admin.py startproject fluentdemo\n\nTo have a standard setup with django-fluent-contents_ integrated, use:\n\n.. code-block:: python\n\n    INSTALLED_APPS += (\n        # The CMS apps\n        'fluent_pages',\n\n        # Required dependencies\n        'mptt',\n        'parler',\n        'polymorphic',\n        'polymorphic_tree',\n        'slug_preview',\n\n        # Optional widget pages via django-fluent-contents\n        'fluent_pages.pagetypes.fluentpage',\n        'fluent_contents',\n        'fluent_contents.plugins.text',\n        'django_wysiwyg',\n\n        # Optional other CMS page types\n        'fluent_pages.pagetypes.redirectnode',\n\n        # enable the admin\n        'django.contrib.admin',\n    )\n\n    DJANGO_WYSIWYG_FLAVOR = \"yui_advanced\"\n\nNote each CMS application is optional. Only ``fluent_pages`` and ``mptt`` are required.\nThe remaining apps add additional functionality to the system.\n\nIn ``urls.py``:\n\n.. code-block:: python\n\n    urlpatterns += patterns('',\n        url(r'', include('fluent_pages.urls'))\n    )\n\nThe database can be created afterwards:\n\n.. code-block:: bash\n\n    ./manage.py migrate\n    ./manage.py runserver\n\n\nCustom page types\n-----------------\n\nThe key feature of this module is the support for custom node types.\nTake a look in the existing types at ``fluent_pages.pagetypes`` to see how it's being done.\n\nIt boils down to creating a package with 2 files:\n\nThe ``models.py`` file should define the custom node type, and any fields it has:\n\n.. code-block:: python\n\n    from django.db import models\n    from django.utils.translation import ugettext_lazy as _\n    from fluent_pages.models import HtmlPage\n    from mysite.settings import RST_TEMPLATE_CHOICES\n\n\n    class RstPage(HtmlPage):\n        \"\"\"\n        A page that renders RST code.\n        \"\"\"\n        rst_content = models.TextField(_(\"RST contents\"))\n        template = models.CharField(_(\"Template\"), max_length=200, choices=RST_TEMPLATE_CHOICES)\n\n        class Meta:\n            verbose_name = _(\"RST page\")\n            verbose_name_plural = _(\"RST pages\")\n\nA ``page_type_plugins.py`` file that defines the metadata, and rendering:\n\n.. code-block:: python\n\n    from fluent_pages.extensions import PageTypePlugin, page_type_pool\n    from .models import RstPage\n\n\n    @page_type_pool.register\n    class RstPagePlugin(PageTypePlugin):\n        model = RstPage\n        sort_priority = 10\n\n        def get_render_template(self, request, rstpage, **kwargs):\n            return rstpage.template\n\nA template could look like:\n\n.. code-block:: html+django\n\n    {% extends \"base.html\" %}\n    {% load markup %}\n\n    {% block headtitle %}{{ page.title }}{% endblock %}\n\n    {% block main %}\n      <h1>{{ page.title }}</h1>\n\n      <div id=\"content\">\n        {{ page.rst_content|restructuredtext }}\n      </div>\n    {% endblock %}\n\nEt, voila: with very little code a custom CMS was just created.\n\nOptionally, a ``model_admin`` can also be defined, to have custom field layouts or extra functionality in the *edit* or *delete* page.\n\nPlugin configuration\n~~~~~~~~~~~~~~~~~~~~\n\nThe plugin can define the following attributes:\n\n* ``model`` - the model for the page type\n* ``model_admin`` - the custom admin to use (must inherit from ``PageAdmin``)\n* ``render_template`` - the template to use for rendering\n* ``response_class`` - the response class (by default ``TemplateResponse``)\n* ``is_file`` - whether the node represents a file, and shouldn't end with a slash.\n* ``can_have_children`` - whether the node type is allowed to have child nodes.\n* ``urls`` - a custom set of URL patterns for sub pages (either a module name, or ``patterns()`` result).\n* ``sort_priority`` - a sorting order in the \"add page\" dialog.\n\nIt can also override the following functions:\n\n* ``get_response(self, request, page, **kwargs)`` - completely redefine the response, instead of using ``response_class``, ``render_template``, etc..\n* ``get_render_template(self, request, page, **kwargs)`` - return the template to render, by default this is ``render_template``.\n* ``get_context(self, request, page, **kwargs)`` - return the template context for the node.\n\nDetails about these attributes is explained in the documentation_.\n\n\nApplication nodes\n~~~~~~~~~~~~~~~~~\n\nAs briefly mentioned above, a page type can have it's own set of URL patterns, via the ``urls`` attribute.\nThis allows implementing page types such as a \"product page\" in the tree,\nwhich automatically has all products from the database as sub pages.\nThe provides ``example`` module demonstrates this concept.\n\nThe URL patterns start at the full path of the page, so it works similar to a regular ``include()`` in the URLconf.\nHowever, a page type may be added multiple times to the tree.\nTo resolve the URLs, there are 2 functions available:\n\n* ``fluent_pages.urlresolvers.app_reverse()`` - this ``reverse()`` like function locates a view attached to a page.\n* ``fluent_pages.urlresolvers.mixed_reverse()`` - this resolver tries ``app_reverse()`` first, and falls back to the standard ``reverse()``.\n\nThe ``mixed_reverse()`` is useful for third party applications which\ncan operate either stand-alone (mounted in the normal URLconf),\nor operate as page type node in combination with *django-fluent-pages*.\nThese features are also used by django-fluent-blogs_ to provide a \"Blog\" page type\nthat can be added to a random point of the tree.\n\n\nAdding pages to the sitemap\n---------------------------\n\nOptionally, the pages can be included in the sitemap.\nAdd the following in ``urls.py``:\n\n.. code-block:: python\n\n    from fluent_pages.sitemaps import PageSitemap\n\n    sitemaps = {\n        'pages': PageSitemap,\n    }\n\n    urlpatterns += patterns('',\n        url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),\n    )\n\n\nContributing\n------------\n\nThis module is designed to be generic. In case there is anything you didn't like about it,\nor think it's not flexible enough, please let us know. We'd love to improve it!\n\nIf you have any other valuable contribution, suggestion or idea,\nplease let us know as well because we will look into it.\nPull requests are welcome too. :-)\n\n\n.. _documentation: https://django-fluent-pages.readthedocs.io/\n.. _django.contrib.sites: https://docs.djangoproject.com/en/dev/ref/contrib/sites/\n.. _django.contrib.sitemaps: https://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/\n\n.. _django-fluent-blogs: https://github.com/django-fluent/django-fluent-blogs\n.. _django-fluent-contents: https://github.com/django-fluent/django-fluent-contents\n.. _django-mptt: https://github.com/django-mptt/django-mptt\n.. _django-parler: https://github.com/edoburu/django-parler\n.. _django-polymorphic: https://github.com/django-polymorphic/django-polymorphic\n.. _django-polymorphic-tree: https://github.com/django-polymorphic/django-polymorphic-tree\n\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "A flexible, scalable CMS with custom node types, and flexible block content.",
    "version": "3.0.2",
    "project_urls": {
        "Download": "https://github.com/edoburu/django-fluent-pages/zipball/master",
        "Homepage": "https://github.com/edoburu/django-fluent-pages"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a6a00524f1e571cfdcc4d6aa0079dde152fb1f99fe69090e5024c92fa948ef53",
                "md5": "54fedce5d95a6ce856d3ddf3efbb930e",
                "sha256": "b425653e64ef9f0b2c13410860b3b558291679847243c61b1e361a76d8be7bc2"
            },
            "downloads": -1,
            "filename": "django_fluent_pages-3.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "54fedce5d95a6ce856d3ddf3efbb930e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 142687,
            "upload_time": "2023-10-16T12:12:00",
            "upload_time_iso_8601": "2023-10-16T12:12:00.911579Z",
            "url": "https://files.pythonhosted.org/packages/a6/a0/0524f1e571cfdcc4d6aa0079dde152fb1f99fe69090e5024c92fa948ef53/django_fluent_pages-3.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "053e38bcc549f495c2bf723065c0a55bd4e5905cfe1667c03a3ae88bccbdfc9f",
                "md5": "dcf0fa17bf4c372cff98436df5b2e235",
                "sha256": "8ad15de35dd9942d34d729d2d6fa579552615f91e2cade49e90336e8b87576e2"
            },
            "downloads": -1,
            "filename": "django-fluent-pages-3.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "dcf0fa17bf4c372cff98436df5b2e235",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 349399,
            "upload_time": "2023-10-16T12:12:02",
            "upload_time_iso_8601": "2023-10-16T12:12:02.778962Z",
            "url": "https://files.pythonhosted.org/packages/05/3e/38bcc549f495c2bf723065c0a55bd4e5905cfe1667c03a3ae88bccbdfc9f/django-fluent-pages-3.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-16 12:12:02",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "edoburu",
    "github_project": "django-fluent-pages",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "tox": true,
    "lcname": "django-fluent-pages"
}
        
Elapsed time: 0.18692s