Metadata-Version: 2.4
Name: djangocms-custom-content
Version: 0.9.0
Summary: Developer framework for integrating custom content models with django CMS.
Author-email: Fabian Braun <fsbraun@gmx.de>
License: BSD-3-Clause
Project-URL: Documentation, https://djangocms-custom-content.readthedocs.io
Project-URL: Issues, https://github.com/fsbraun/djangocms-custom-content/issues
Project-URL: Source, https://github.com/fsbraun/djangocms-custom-content
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Framework :: Django :: 6.1
Classifier: Framework :: Django CMS
Classifier: Framework :: Django CMS :: 5.0
Classifier: Framework :: Django CMS :: 5.1
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: django-cms>=5
Provides-Extra: djangocms-versioning
Requires-Dist: djangocms-versioning>=2.3; extra == "djangocms-versioning"
Provides-Extra: test
Requires-Dist: djangocms-custom-content[djangocms-versioning]; extra == "test"
Requires-Dist: pre-commit>=3; extra == "test"
Requires-Dist: pytest>=7; extra == "test"
Requires-Dist: pytest-cov>=5; extra == "test"
Requires-Dist: pytest-django>=4; extra == "test"
Dynamic: license-file

========================
djangocms-custom-content
========================

|PyPiVersion| |PyVersion| |DjVersion| |CmsVersion| |Coverage|

**Custom content for django CMS — without the boilerplate.**

Building custom content in django CMS by hand means wiring up a grouper,
versioning, a grouper admin, frontend editing, an app hook and migrations
yourself. ``djangocms-custom-content`` does all of that — you write the model.

Write this…
===========

.. code-block:: python

    from django.db import models
    from djangocms_custom_content.models import AbstractCustomGrouper, AbstractCustomContent

    class Article(AbstractCustomGrouper):
        pass

    class ArticleContent(AbstractCustomContent):
        article = models.ForeignKey(Article, on_delete=models.CASCADE)
        language = models.CharField(max_length=10)
        slug = models.SlugField()
        title = models.CharField(max_length=200)
        body = models.TextField()

        class CMSConfig:
            enable_versioning = True
            enable_frontend_editing = True
            apphook = True

…and that model (plus a few lines of grouper admin) gives you, for free:

* per-language draft/publish version history
* frontend, double-click editing inside the page
* a detail view at a clean URL, with ``get_absolute_url()`` injected — swap in
  your own view or add extra URLs when you outgrow the default
* a grouper admin to create and manage content

Want related content? Add **one line** to the grouper —
``authors = RelationField("people.Person", ordered=True)`` — and the admin renders
a sortable autocomplete, anchored to the grouper so the link survives every new
version.

.. note::

    **Status: 0.9 — usable, pre-1.0.** The public API is settled and written down
    (see `API stability
    <https://djangocms-custom-content.readthedocs.io/en/latest/reference/api_stability.html>`_),
    but a ``0.x`` minor release may still carry a breaking change — the changelog
    says so when it does. Feedback and bug reports are very welcome.

Why you'll want it
==================

* **Write the model, skip the plumbing** — versioning, grouper admin, frontend
  editing, app hooks and migrations are handled.
* **Relations that survive versioning** — related content is anchored to the
  grouper, so links don't break when a new version is published.
* **Sortable related-content widgets, free** — every relation renders as an
  autocomplete multi-select in the admin, drag-sortable when ordered.
* **Relate to anything without touching it** — generic relations need no foreign
  key or migration on the target model.
* **Multi-language & versioned** — per-language draft/publish history per content
  model.
* **Batteries included** — complete blog, people, categories and services apps,
  supported and migrated, to install as-is or read and adapt.
* **Current django CMS and Django** — see the badges above for the supported
  releases.

See it work in two minutes
==========================

Don't build anything yet — turn on a bundled example and click around first::

    pip install djangocms-custom-content[djangocms-versioning]

(Versioning is optional; drop the extra if you don't want draft/publish history.)

Add the blog (plus the apps it relates to) to ``INSTALLED_APPS`` and migrate::

    INSTALLED_APPS = [
        # ... django CMS and its dependencies ...
        "djangocms_custom_content",
        "djangocms_custom_content.contrib.people",
        "djangocms_custom_content.contrib.categories",
        "djangocms_custom_content.contrib.blog",
    ]

    python manage.py migrate

That's it — a versioned, frontend-editable blog in the admin, with sortable
authors and categories relations and ready-to-place CMS plugins, no models
written. Then build your own by following the documentation:

https://djangocms-custom-content.readthedocs.io/

Bundled apps
============

``djangocms_custom_content.contrib`` ships complete, installable applications
(models + admin + django CMS plugins). Install and rely on them, or read them as
worked examples and adapt — either way their schema changes arrive as migrations
that upgrade an existing database:

* ``djangocms_custom_content.contrib.people``: ``Person`` grouper/content (a
  versioned grouper without a language field) + "Person teaser" plugin, and an
  app hook giving every person a detail URL
* ``djangocms_custom_content.contrib.categories``: ``FlatCategory`` — a
  grouper-less taxonomy used as a relation target + "Category list" plugin
* ``djangocms_custom_content.contrib.services``: a versioned, frontend-editable
  ``Service``/``ServiceContent`` pair + "Service teaser" and "Featured services"
  plugins
* ``djangocms_custom_content.contrib.blog``: blog posts with ordered ``authors``
  and ``categories`` relations + "Blog post" teaser and a paginated
  "Blog post list" plugin

To enable one (or more), add the module(s) to ``INSTALLED_APPS`` and run migrations::

    INSTALLED_APPS = [
        ...,
        'djangocms_custom_content',
        'djangocms_custom_content.contrib.people',  # each app is optional
        'djangocms_custom_content.contrib.services',
        'djangocms_custom_content.contrib.categories',
        'djangocms_custom_content.contrib.blog',
        ...,
    ]

    python manage.py migrate

Contributing
============

Contributions are welcome! Please feel free to submit a Pull Request.

License
=======

This project is licensed under the BSD-3-Clause License.


.. |PyPiVersion| image:: https://img.shields.io/pypi/v/djangocms-custom-content?style=flat-square
    :target: https://pypi.python.org/pypi/djangocms-custom-content
    :alt: Latest PyPI version

.. |PyVersion| image:: https://img.shields.io/pypi/pyversions/djangocms-custom-content?style=flat-square
    :target: https://pypi.python.org/pypi/djangocms-custom-content
    :alt: Python versions

.. |DjVersion| image:: https://img.shields.io/pypi/frameworkversions/django/djangocms-custom-content?style=flat-square
    :target: https://pypi.python.org/pypi/djangocms-custom-content
    :alt: Django versions

.. |CmsVersion| image:: https://img.shields.io/pypi/frameworkversions/django-cms/djangocms-custom-content?style=flat-square
    :target: https://pypi.python.org/pypi/djangocms-custom-content
    :alt: django CMS versions

.. |Coverage| image:: https://codecov.io/gh/fsbraun/djangocms-custom-content/graph/badge.svg?token=GESjKzHSXl&style=flat-square
    :target: https://codecov.io/gh/fsbraun/djangocms-custom-content
