nephila/djangocms-blog

View on GitHub
docs/features/admin_customization.rst

Summary

Maintainability
Test Coverage
.. _admin_customization:

###################
Admin customization
###################

As any other django model admin, :py:class:`PostAdmin` can be customized by extending it adding a subclass in one of the
project's applications.

.. code-block:: python
   :name: project_app/admin.py

    admin.site.unregister(Post)
    @admin.register(Post)
    class CustomPostAdmin(PostAdmin):
        ...
        you_attributes_and_methods


*************************
Customizing the fieldsets
*************************

Due to the logic in :py:meth:`djangocms_blog.admin.PostAdmin.get_fieldsets` method, it's advised to customize the
fieldsets by overriding two private attributes :py:attr:`djangocms_blog.admin.PostAdmin._fieldsets` and
:py:attr:`djangocms_blog.admin.PostAdmin._fieldset_extra_fields_position`.

_fieldsets
=================

``_fieldsets`` attribute follow the standard `Django Admin fieldset`_ structure. This is the primary source for customization.

You can freely rearrange and remove fields from this structure as you would to in a normal ``fieldsets`` attribute; the only
caveat is that you must ensure consistency extra fields position set by ``_fieldset_extra_fields_position``.


_fieldset_extra_fields_position
===============================

As some fields are managed by settings and apphook config, they are added to the final ``fieldsets`` by ``PostAdmin.get_fieldsets``;
you can customize their position (or hide them) by overriding ``_fieldset_extra_fields_position`` attribute.

The attribute is a dictionary containing the fields name as key, and by providing their position in the fieldsets as tuple.

Use a 2-item tuple if the field must be appended at the row level (e.g.: ``(None, {"fields": ["field_a", "field_b"]})``) or
a 3-item tuple if the field must be appended in a subgroup (e.g.: ``(None, {"fields": ["field_a", ["field_b"[]})``.

Example
===============================

.. code-block:: python
   :name: my_app/admin.py

    admin.site.unregister(Post)
    @admin.register(Post)
    class CustomPostAdmin(PostAdmin):
        ...
        _fieldsets = [
            (None, {"fields": ["title", "subtitle", "slug", "publish", "categories"]}),
            (
                _("Info"),
                {
                    "fields": [["tags"], ["date_published", "date_published_end", "date_featured"], "app_config", "enable_comments"],
                    "classes": ("collapse",),
                },
            ),
            (
                _("Images"),
                {"fields": [["main_image", "main_image_thumbnail", "main_image_full"]], "classes": ("collapse",)},
            ),
            (_("SEO"), {"fields": [["meta_description", "meta_title", "meta_keywords"]], "classes": ("collapse",)}),
        ]
        _fieldset_extra_fields_position = {
            "abstract": [0, 1],
            "post_text": [0, 1],
            "sites": [1, 1, 0],
            "author": [1, 1],
            "enable_liveblog": None,
            "related": [1, 1, 0],
        }

This example will result in:

* ``"enable_liveblog"``: hidden even if enabled in settings
* ``"sites"``: added in the same subgroup as ``"tags"``
* ``"author"``: appended after the ``"enable_comments"`` field
* ``"app_config"`` field moved to ``"Info"`` fieldset


.. _admin_filter_function:

Filter function
===============

You can add / remove / filter fields at runtime by defining a method on you custom admin and proving its name in :ref:`BLOG_ADMIN_POST_FIELDSET_FILTER <ADMIN_POST_FIELDSET_FILTER>`.

Method must take the following arguments:

* ``fsets``: current fieldsets dictionary
* ``request``: current admin request
* ``obj`` (default: ``None``): current post object (if available)

and it must return the modified fieldsets dictionary.

Function example:

.. code-block:: python

    def fieldset_filter_function(fsets, request, obj=None):
        if request.user.groups.filter(name='Editor').exists():
            fsets[1][1]['fields'][0].append('author')  # adding 'author' field if user is Editor
        return fsets


.. _django admin fieldset: https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets