=============================
Django Admin Toolkit
=============================
.. image:: https://badge.fury.io/py/django-admin-toolkit.svg/?style=flat-square
:target: https://badge.fury.io/py/django-admin-toolkit
.. image:: https://readthedocs.org/projects/pip/badge/?version=latest&style=flat-square
:target: https://django-admin-toolkit.readthedocs.io/en/latest/
.. image:: https://img.shields.io/coveralls/github/frankhood/django-admin-toolkit/master?style=flat-square
:target: https://coveralls.io/github/frankhood/django-admin-toolkit?branch=master
:alt: Coverage Status
This package offers a wide choice of admin mixins to best customize your Django admin site,
with a multitude of useful features that will simplify your development.
Documentation
-------------
The full documentation is at https://django-admin-toolkit.readthedocs.io.
Quickstart
----------
Install Django Admin Toolkit::
pip install django-admin-toolkit
Add it to your ``INSTALLED_APPS``:
.. code-block:: python
INSTALLED_APPS = (
...
'admin_toolkit',
...
)
AfterSaveAdminMixin
_________________________
Through this mixin it is possible to insert your own logics at the end of saving the model via Django admin site.
.. code-block:: python
from admin_toolkit.admin_mixins import AfterSaveAdminMixin
@admin.register(app_models.AfterSaveExampleModel)
class AfterSaveExampleModelAdmin(AfterSaveAdminMixin, admin.ModelAdmin):
list_display = ("__str__", "test_text")
fields = ("test_text",)
AllReadonlyAdminMixin
_____________________
This admin mixin will turn all your admin fields into read only fields.
.. code-block:: python
from admin_toolkit.admin_mixins import AllReadonlyAdminMixin
@admin.register(app_models.AllReadonlyExampleModel)
class AllReadonlyExampleModelAdmin(AllReadonlyAdminMixin, admin.ModelAdmin):
list_display = ("id", "test_text",)
fields = ("test_text",)
In the image you can see that there is no permission to add other objects because in the mixin ``has_add_permission()`` returns False.
.. image:: docs/readme_images/all_readonly_changelist.png
:alt: ChangeList Image.
And in the detail page it is possible to see that all the fields present are readonly.
.. image:: docs/readme_images/all_readonly_changeform.png
:alt: ChangeForm Image.
AllReadonlyAdminInlineMixin
___________________________
This admin mixin will turn all your inline admin fields into read only fields.
.. code-block:: python
from admin_toolkit.admin_mixins import AllReadonlyAdminInlineMixin
class AllReadonlyExampleModelAdminInline(AllReadonlyAdminInlineMixin, admin.TabularInline):
model = app_models.AllReadonlyExampleModel
fields = ("test_text",)
In the image you can see that there is no permission to add other objects in inline because in the mixin ``has_add_permission()`` returns False.
And it is possible to see that all the fields present are readonly.
.. image:: docs/readme_images/all_readonly_inline.png
:alt: Inline Image.
BaseAdminMixin
______________
This mixin provides a wide variety of display methods for all (or almost all)
of the readonly fields that you will need to display in your Django admin site.
Create your model and add the ``admin_changelist_url()`` method and the ``get_ct()`` method to it.
.. code-block:: python
class BaseExampleModel(models.Model):
objects = app_managers.BaseExampleModelManager.from_queryset(app_queryset.BaseExampleModelQuerySet)()
test_boolean = models.BooleanField(
"Test bool",
null=True
)
test_datetime = models.DateTimeField(
"Test datetime"
)
test_fk = models.ForeignKey(
"example.BaseExampleFkModel",
verbose_name="Test fk",
on_delete=models.CASCADE,
related_name="example_for_base_admin_mixins"
)
test_image = models.ImageField(
"Test image",
upload_to="example/images/"
)
test_m2m = models.ManyToManyField(
"example.BaseExampleM2MModel",
related_name="example_for_base_admin_mixins",
)
example_generic_relation_model_for_base_admin_mixin = GenericRelation(
"example.BaseExampleGenericRelationModel",
related_query_name='example_model_for_base_admin_mixin'
)
def __str__(self):
return str(self.id)
@classmethod
def admin_changelist_url(cls):
return reverse("admin:example_baseexamplemodel_changelist")
def get_ct(self):
return ContentType.objects.get(
app_label=self._meta.app_label, model=self._meta.model_name
)
Then register ``BaseExampleModel`` and start to add all yours displays.
.. code-block:: python
from admin_toolkit.admin_mixins import BaseAdminMixin
@admin.register(app_models.BaseExampleModel)
class BaseExampleModelAdmin(BaseAdminMixin, admin.ModelAdmin):
list_display = (
"__str__",
"display_test_boolean",
"display_test_datetime",
"display_test_date",
"display_test_time",
"display_test_fk",
"display_test_image",
"display_test_m2m",
)
fields = ("test_boolean", "test_datetime", "test_fk", "test_image", "test_m2m")
readonly_fields = (
"display_test_boolean",
"display_test_datetime",
"display_test_date",
"display_test_time",
"display_test_fk",
"display_test_image",
"display_test_m2m",
"display_generic_relation",
)
#. How to display a boolean field:
.. code-block:: python
@mark_safe
def display_test_boolean(self, obj):
if obj and obj.test_boolean:
return self._display_boolean(obj.test_boolean)
return ""
.. image:: docs/readme_images/base_example_boolean.png
:alt: BaseAdminMixin boolean field Image.
#. How to display a datetime (work only with datetime):
.. code-block:: python
@mark_safe
def display_test_datetime(self, obj):
if obj and obj.test_datetime:
return self._display_datetime(obj.test_datetime)
return ""
.. image:: docs/readme_images/base_example_datetime.png
:alt: BaseAdminMixin datetime field Image.
#. How to display a date (work only with datetime):
.. code-block:: python
@mark_safe
def display_test_date(self, obj):
if obj and obj.test_datetime:
return self._display_date(obj.test_datetime)
return ""
.. image:: docs/readme_images/base_example_date.png
:alt: BaseAdminMixin date field Image.
#. How to display a time (work only with datetime):
.. code-block:: python
@mark_safe
def display_test_time(self, obj):
if obj and obj.test_datetime:
return self._display_time(obj.test_datetime)
return ""
.. image:: docs/readme_images/base_example_time.png
:alt: BaseAdminMixin time field Image.
#. How to display a ForeignKey:
.. code-block:: python
@mark_safe
def display_test_fk(self, obj):
if obj and obj.test_fk:
return self._display_fk_object(obj.test_fk)
return ""
.. image:: docs/readme_images/base_example_fk.png
:alt: BaseAdminMixin FK field Image.
#. How to display an image:
.. code-block:: python
@mark_safe
def display_test_image(self, obj):
if obj and obj.test_image:
return self._display_image(obj.test_image)
return ""
.. image:: docs/readme_images/base_example_image.png
:alt: BaseAdminMixin image field Image.
#. How to display a ManyToMany:
.. code-block:: python
@mark_safe
def display_test_m2m(self, obj):
if obj and obj.test_m2m:
return self._display_m2m_objects(
obj, m2m_field_name="test_m2m", label="Example M2Ms"
)
return ""
.. image:: docs/readme_images/base_example_m2m.png
:alt: BaseAdminMixin image field Image.
#. How to display a GenericRelation:
.. code-block:: python
@mark_safe
def display_generic_relation(self, obj):
if obj and obj.id:
return self._display_generic_related_objects(
obj,
"example_generic_relation_model_for_base_admin_mixin",
"Example Generic Relations"
)
return ""
.. image:: docs/readme_images/base_example_generic_relation.png
:alt: BaseAdminMixin generic relation field Image.
This is the final changelist result:
.. image:: docs/readme_images/base_example_changelist.png
:alt: BaseAdminMixin example result ChangeList Image.
ConfigurableWidgetsAdminMixin
_____________________________
Use ConfigurableWidgetsMixinAdmin if you want to customize quickly
default widget/label/help_text or every related admin form configurations
without doing modifications of the auto created ModelForm.
In this example I am going to modify the help_text and the widgets of the three fields.
.. code-block:: python
# ==================
# project/models.py
# ==================
class ConfigurableWidgetsExampleModel(models.Model):
objects = ConfigurableWidgetsExampleModelManager.from_queryset(
ConfigurableWidgetsExampleModelQuerySet)()
test_text = models.CharField("Test Text", max_length=500, default="", blank=True)
test_fk = models.ForeignKey(
ConfigurableWidgetsExampleFKModel,
verbose_name="Test FK",
on_delete=models.SET_NULL,
null=True
)
test_m2m = models.ManyToManyField(
ConfigurableWidgetsExampleM2MModel,
verbose_name="Test M2M"
)
class Meta:
verbose_name = "Configurable widgets example model"
verbose_name_plural = "Configurable widgets example models"
# ==================
# project/admin.py
# ==================
from admin_toolkit.admin_mixins import ConfigurableWidgetsAdminMixin
@admin.register(app_models.ConfigurableWidgetsExampleModel)
class ConfigurableWidgetsExampleModelAdmin(ConfigurableWidgetsAdminMixin, admin.ModelAdmin):
list_display = ("id", "test_text",)
fieldsets = (
(None, {"fields": (
("test_text",),
("test_fk", "test_m2m",),
)}),
)
filter_horizontal = ("test_m2m",)
dbfield_overrides = {
"test_text": {"help_text": "Test Text Example help text", "widget": forms.Textarea},
}
fkfield_overrides = {
"test_fk": {"help_text": "Test FK Example help text", "widget": forms.RadioSelect},
}
m2mfield_overrides = {
"test_m2m": {"help_text": "Test M2M Example help text", "widget": forms.CheckboxSelectMultiple}
}
This is the final result:
.. image:: docs/readme_images/configurable_widgets_changeform.png
:alt: Configurable Widgets Mixin change form Image.
DetailInInlineAdminMixin
________________________
This admin mixin allows you to have in each line of the inline a button that redirects to the change form of the element created.
.. code-block:: python
from admin_toolkit.admin_mixins import DetailInInlineAdminMixin
class DetailInInlineExampleModelAdminInline(DetailInInlineAdminMixin, admin.TabularInline):
fields = ("test_text",)
model = app_models.DetailInInlineExampleModel
This is the final result:
.. image:: docs/readme_images/detail_in_inline_changeform.png
:alt: Configurable Widgets Mixin change form Image.
EmptyValueAdminMixin
____________________
This admin mixin allows you to define a label for a foreign key field for the empty value.
.. code-block:: python
@admin.register(app_models.EmptyValueExampleModel)
class EmptyValueExampleModelAdmin(EmptyValueAdminMixin, admin.ModelAdmin):
list_display = ("id", "test_text", "test_fk",)
fields = ("test_text", "test_fk")
empty_values = {
"test_fk": _("NO TEST FK")
}
This is the final result:
.. image:: docs/readme_images/empty_value_change_form.png
:alt: Empty value admin mixin change form Image.
ExtraButtonAdminMixin
_____________________
This admin mixin allows you to add extra buttons links next to the add button in a simple and immediate way.
.. code-block:: python
@admin.register(app_models.ExtraButtonExampleModel)
class ExtraButtonExampleModelAdmin(ExtraButtonAdminMixin, admin.ModelAdmin):
list_display = ("id", "test_text")
fields = ("test_text",)
extra_button = [
{
"label": "Example Extra Button",
"url": "http://example.com",
"class": ""
}
]
This is the final result:
.. image:: docs/readme_images/extra_button_changelist.png
:alt: Extra button admin mixin changelist Image.
FloatingAdminMixin
__________________
This mixin makes the list filters collapsible vertically
in such a way as to have more space for any columns that otherwise would not be seen.
.. code-block:: python
@admin.register(app_models.FloatingExampleModel)
class FloatingExampleModelAdmin(FloatingAdminMixin, admin.ModelAdmin):
list_display = ("id", "test_text")
list_filter = ("test_text",)
fields = ("test_text",)
This is the final result:
#. When the list filter is collapsed.
.. image:: docs/readme_images/floating_changelist_collapsed.png
:alt: Floating admin mixin collapsed in changelist Image.
#. When the list filter is decollapsed.
.. image:: docs/readme_images/floating_changelist_decollapsed.png
:alt: Floating admin mixin decollapsed in changelist Image.
ImprovedRawIdFieldsAdminMixin
_____________________________
This admin mixin allows you to view the link of the changelist/changeform
of the selected objects inside the raw_id_field on ForeignKey and ManyToMany.
.. code-block:: python
@admin.register(app_models.ImprovedRawIdFieldsExampleModel)
class ImprovedRawIdFieldsExampleModelAdmin(ImprovedRawIdFieldsAdminMixin, admin.ModelAdmin):
improved_raw_id_fields = ["test_fk", "test_m2m"]
list_display = ("id", "test_name",)
fieldsets = (
(None, {"fields": (
("test_name",),
("test_fk", "test_m2m"),
)}),
)
This is the result:
#. When adding an object.
.. image:: docs/readme_images/improve_raw_fields_changeform_add.png
:alt: Improve Raw Id Fields admin mixin in changeform add Image.
#. When changing an object.
.. image:: docs/readme_images/improve_raw_fields_changeform_change.png
:alt: Improve Raw Id Fields admin mixin in changeform change Image.
ADMIN FILTERS
_____________
This package also comes with a set of list filters
that you can use to make it easier to write filters with special queries.
.. image:: docs/readme_images/admin_filters_changelist.png
:alt: Admin filters changelist Image.
CustomRelatedSelectFilter
=========================
Using this filter on Many to Many or Foreign Key it is possible
to have a list of elements associated with the field inserted in the list_filter
which becomes a select if the list exceeds 4 elements ordered according to a specific
field of the foreign key or many to many.
.. code-block:: python
class CustomRelatedSelectFilterForTestFK(admin_filters.CustomRelatedSelectFilter):
def get_related_order(self):
return ["test_char"]
class CustomRelatedSelectFilterForTestM2M(admin_filters.CustomRelatedSelectFilter):
def get_related_order(self):
return ["test_char"]
@admin.register(app_models.AdminFilterExampleModel)
class AdminFilterExampleModelAdmin(admin.ModelAdmin):
list_display = ("id", "test_char", "get_test_choice_display", "test_fk")
list_filter = (
("test_fk", CustomRelatedSelectFilterForTestFK),
("test_m2m", CustomRelatedSelectFilterForTestM2M),
)
fieldsets = (
(None, {"fields": (
("test_char", "test_choice", "test_fk", "test_m2m"),
)}),
)
This are the results:
* For the field test_fk:
.. image:: docs/readme_images/admin_custom_related_filter_fk.png
:alt: Admin custom related filter for FK
* For the field test_m2m:
.. image:: docs/readme_images/admin_custom_related_filter_m2m.png
:alt: Admin custom related filter for M2M
RelatedSelectFilter
===================
Using this filter on Many to Many or Foreign Key it is possible
to have a list of elements associated with the field inserted in the list_filter
which becomes a select if the list exceeds 4 elements.
.. code-block:: python
@admin.register(app_models.AdminFilterExampleModel)
class AdminFilterExampleModelAdmin(admin.ModelAdmin):
list_display = ("id", "test_char", "get_test_choice_display", "test_fk")
list_filter = (
("test_fk", RelatedSelectFilter),
)
fieldsets = (
(None, {"fields": (
("test_char", "test_choice", "test_fk", "test_m2m"),
)}),
)
SelectFilter
============
This filter can be used on fields that contain choices to be able to display them in a select instead of seeing a bulleted list.
.. code-block:: python
@admin.register(app_models.AdminFilterExampleModel)
class AdminFilterExampleModelAdmin(admin.ModelAdmin):
list_display = ("id", "test_char", "get_test_choice_display", "test_fk")
list_filter = (
("test_choice", SelectFilter),
)
fieldsets = (
(None, {"fields": (
("test_char", "test_choice", "test_fk", "test_m2m"),
)}),
)
This is the result:
.. image:: docs/readme_images/admin_select_filter.png
:alt: Admin select filter for choices Image.
SimpleBooleanListFilter
=======================
This filter can be used to give a given query a boolean filter like this example:
.. code-block:: python
# tests/example/admin_filters.py
class SimpleBooleanTestInTestCharFilter(admin_filters.SimpleBooleanListFilter):
title = "Test word is in Test char?"
parameter_name = "test_char"
def get_true_queryset_values(self, queryset):
return queryset.filter(test_char__icontains="test")
def get_false_queryset_values(self, queryset):
return queryset.exclude(test_char__icontains="test")
# tests/example/admin.py
from tests.example import admin_filters as app_admin_filters
@admin.register(app_models.AdminFilterExampleModel)
class AdminFilterExampleModelAdmin(admin.ModelAdmin):
list_display = ("id", "test_char", "get_test_choice_display", "test_fk")
list_filter = (
app_admin_filters.SimpleBooleanTestInTestCharFilter,
)
fieldsets = (
(None, {"fields": (
("test_char", "test_choice", "test_fk", "test_m2m"),
)}),
)
This is the result:
.. image:: docs/readme_images/admin_boolean_filters.png
:alt: Admin boolean filter Image.
Running Tests
-------------
Does the code actually work?
::
source <YOURVIRTUALENV>/bin/activate
(myenv) $ pip install tox
(myenv) $ tox
Development commands
---------------------
::
pip install -r requirements_dev.txt
invoke -l
Credits
-------
Tools used in rendering this package:
* Cookiecutter_
* `cookiecutter-djangopackage`_
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`cookiecutter-djangopackage`: https://github.com/pydanny/cookiecutter-djangopackage
History
-------
0.1.0 (2021-11-10)
__________________
* First release on PyPI.
0.1.1 (2021-11-10)
__________________
* Fixed HISTORY.rst problems with long_description_content_type
0.1.3 (2021-11-10)
__________________
* Fixed HISTORY.rst problems changing + to _ for versions.
0.1.4 (2021-12-6)
__________________
* Fixed bug on ConfigurableWidgetsAdminMixin.
Raw data
{
"_id": null,
"home_page": "https://github.com/frankhood/django-admin-toolkit",
"name": "django-admin-toolkit",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "django-admin-toolkit",
"author": "FrankHood Business Solutions srl",
"author_email": "info@frankhood.it",
"download_url": "https://files.pythonhosted.org/packages/cd/4e/63b77caf81bde4dabaf883b39874e708ed56fdadb8093efc684c97527e49/django-admin-toolkit-0.1.9.tar.gz",
"platform": null,
"description": "=============================\nDjango Admin Toolkit\n=============================\n\n.. image:: https://badge.fury.io/py/django-admin-toolkit.svg/?style=flat-square\n :target: https://badge.fury.io/py/django-admin-toolkit\n\n.. image:: https://readthedocs.org/projects/pip/badge/?version=latest&style=flat-square\n :target: https://django-admin-toolkit.readthedocs.io/en/latest/\n\n.. image:: https://img.shields.io/coveralls/github/frankhood/django-admin-toolkit/master?style=flat-square\n :target: https://coveralls.io/github/frankhood/django-admin-toolkit?branch=master\n :alt: Coverage Status\n\nThis package offers a wide choice of admin mixins to best customize your Django admin site,\nwith a multitude of useful features that will simplify your development.\n\nDocumentation\n-------------\n\nThe full documentation is at https://django-admin-toolkit.readthedocs.io.\n\nQuickstart\n----------\n\nInstall Django Admin Toolkit::\n\n pip install django-admin-toolkit\n\nAdd it to your ``INSTALLED_APPS``:\n\n.. code-block:: python\n\n INSTALLED_APPS = (\n ...\n 'admin_toolkit',\n ...\n )\n\nAfterSaveAdminMixin\n_________________________\n\nThrough this mixin it is possible to insert your own logics at the end of saving the model via Django admin site.\n\n.. code-block:: python\n\n from admin_toolkit.admin_mixins import AfterSaveAdminMixin\n\n @admin.register(app_models.AfterSaveExampleModel)\n class AfterSaveExampleModelAdmin(AfterSaveAdminMixin, admin.ModelAdmin):\n list_display = (\"__str__\", \"test_text\")\n fields = (\"test_text\",)\n\n\nAllReadonlyAdminMixin\n_____________________\n\nThis admin mixin will turn all your admin fields into read only fields.\n\n\n.. code-block:: python\n\n from admin_toolkit.admin_mixins import AllReadonlyAdminMixin\n\n @admin.register(app_models.AllReadonlyExampleModel)\n class AllReadonlyExampleModelAdmin(AllReadonlyAdminMixin, admin.ModelAdmin):\n list_display = (\"id\", \"test_text\",)\n fields = (\"test_text\",)\n\nIn the image you can see that there is no permission to add other objects because in the mixin ``has_add_permission()`` returns False.\n\n.. image:: docs/readme_images/all_readonly_changelist.png\n :alt: ChangeList Image.\n\nAnd in the detail page it is possible to see that all the fields present are readonly.\n\n.. image:: docs/readme_images/all_readonly_changeform.png\n :alt: ChangeForm Image.\n\nAllReadonlyAdminInlineMixin\n___________________________\n\nThis admin mixin will turn all your inline admin fields into read only fields.\n\n.. code-block:: python\n\n from admin_toolkit.admin_mixins import AllReadonlyAdminInlineMixin\n\n class AllReadonlyExampleModelAdminInline(AllReadonlyAdminInlineMixin, admin.TabularInline):\n model = app_models.AllReadonlyExampleModel\n fields = (\"test_text\",)\n\nIn the image you can see that there is no permission to add other objects in inline because in the mixin ``has_add_permission()`` returns False.\nAnd it is possible to see that all the fields present are readonly.\n\n.. image:: docs/readme_images/all_readonly_inline.png\n :alt: Inline Image.\n\n\nBaseAdminMixin\n______________\n\nThis mixin provides a wide variety of display methods for all (or almost all)\nof the readonly fields that you will need to display in your Django admin site.\n\n\nCreate your model and add the ``admin_changelist_url()`` method and the ``get_ct()`` method to it.\n\n.. code-block:: python\n\n class BaseExampleModel(models.Model):\n objects = app_managers.BaseExampleModelManager.from_queryset(app_queryset.BaseExampleModelQuerySet)()\n\n test_boolean = models.BooleanField(\n \"Test bool\",\n null=True\n )\n test_datetime = models.DateTimeField(\n \"Test datetime\"\n )\n test_fk = models.ForeignKey(\n \"example.BaseExampleFkModel\",\n verbose_name=\"Test fk\",\n on_delete=models.CASCADE,\n related_name=\"example_for_base_admin_mixins\"\n )\n test_image = models.ImageField(\n \"Test image\",\n upload_to=\"example/images/\"\n )\n test_m2m = models.ManyToManyField(\n \"example.BaseExampleM2MModel\",\n related_name=\"example_for_base_admin_mixins\",\n )\n example_generic_relation_model_for_base_admin_mixin = GenericRelation(\n \"example.BaseExampleGenericRelationModel\",\n related_query_name='example_model_for_base_admin_mixin'\n )\n\n def __str__(self):\n return str(self.id)\n\n @classmethod\n def admin_changelist_url(cls):\n return reverse(\"admin:example_baseexamplemodel_changelist\")\n\n def get_ct(self):\n return ContentType.objects.get(\n app_label=self._meta.app_label, model=self._meta.model_name\n )\n\n\nThen register ``BaseExampleModel`` and start to add all yours displays.\n\n.. code-block:: python\n\n from admin_toolkit.admin_mixins import BaseAdminMixin\n\n\n @admin.register(app_models.BaseExampleModel)\n class BaseExampleModelAdmin(BaseAdminMixin, admin.ModelAdmin):\n list_display = (\n \"__str__\",\n \"display_test_boolean\",\n \"display_test_datetime\",\n \"display_test_date\",\n \"display_test_time\",\n \"display_test_fk\",\n \"display_test_image\",\n \"display_test_m2m\",\n )\n fields = (\"test_boolean\", \"test_datetime\", \"test_fk\", \"test_image\", \"test_m2m\")\n readonly_fields = (\n \"display_test_boolean\",\n \"display_test_datetime\",\n \"display_test_date\",\n \"display_test_time\",\n \"display_test_fk\",\n \"display_test_image\",\n \"display_test_m2m\",\n \"display_generic_relation\",\n )\n\n\n#. How to display a boolean field:\n\n .. code-block:: python\n\n @mark_safe\n def display_test_boolean(self, obj):\n if obj and obj.test_boolean:\n return self._display_boolean(obj.test_boolean)\n return \"\"\n\n\n .. image:: docs/readme_images/base_example_boolean.png\n :alt: BaseAdminMixin boolean field Image.\n\n#. How to display a datetime (work only with datetime):\n\n .. code-block:: python\n\n @mark_safe\n def display_test_datetime(self, obj):\n if obj and obj.test_datetime:\n return self._display_datetime(obj.test_datetime)\n return \"\"\n\n .. image:: docs/readme_images/base_example_datetime.png\n :alt: BaseAdminMixin datetime field Image.\n\n#. How to display a date (work only with datetime):\n\n .. code-block:: python\n\n @mark_safe\n def display_test_date(self, obj):\n if obj and obj.test_datetime:\n return self._display_date(obj.test_datetime)\n return \"\"\n\n .. image:: docs/readme_images/base_example_date.png\n :alt: BaseAdminMixin date field Image.\n\n#. How to display a time (work only with datetime):\n\n .. code-block:: python\n\n @mark_safe\n def display_test_time(self, obj):\n if obj and obj.test_datetime:\n return self._display_time(obj.test_datetime)\n return \"\"\n\n .. image:: docs/readme_images/base_example_time.png\n :alt: BaseAdminMixin time field Image.\n\n#. How to display a ForeignKey:\n\n .. code-block:: python\n\n @mark_safe\n def display_test_fk(self, obj):\n if obj and obj.test_fk:\n return self._display_fk_object(obj.test_fk)\n return \"\"\n\n .. image:: docs/readme_images/base_example_fk.png\n :alt: BaseAdminMixin FK field Image.\n\n#. How to display an image:\n\n .. code-block:: python\n\n @mark_safe\n def display_test_image(self, obj):\n if obj and obj.test_image:\n return self._display_image(obj.test_image)\n return \"\"\n\n .. image:: docs/readme_images/base_example_image.png\n :alt: BaseAdminMixin image field Image.\n\n#. How to display a ManyToMany:\n\n .. code-block:: python\n\n @mark_safe\n def display_test_m2m(self, obj):\n if obj and obj.test_m2m:\n return self._display_m2m_objects(\n obj, m2m_field_name=\"test_m2m\", label=\"Example M2Ms\"\n )\n return \"\"\n\n .. image:: docs/readme_images/base_example_m2m.png\n :alt: BaseAdminMixin image field Image.\n\n#. How to display a GenericRelation:\n\n .. code-block:: python\n\n @mark_safe\n def display_generic_relation(self, obj):\n if obj and obj.id:\n return self._display_generic_related_objects(\n obj,\n \"example_generic_relation_model_for_base_admin_mixin\",\n \"Example Generic Relations\"\n )\n return \"\"\n\n .. image:: docs/readme_images/base_example_generic_relation.png\n :alt: BaseAdminMixin generic relation field Image.\n\nThis is the final changelist result:\n\n.. image:: docs/readme_images/base_example_changelist.png\n :alt: BaseAdminMixin example result ChangeList Image.\n\n\nConfigurableWidgetsAdminMixin\n_____________________________\n\nUse ConfigurableWidgetsMixinAdmin if you want to customize quickly\ndefault widget/label/help_text or every related admin form configurations\nwithout doing modifications of the auto created ModelForm.\n\nIn this example I am going to modify the help_text and the widgets of the three fields.\n\n.. code-block:: python\n\n # ==================\n # project/models.py\n # ==================\n\n class ConfigurableWidgetsExampleModel(models.Model):\n objects = ConfigurableWidgetsExampleModelManager.from_queryset(\n ConfigurableWidgetsExampleModelQuerySet)()\n\n test_text = models.CharField(\"Test Text\", max_length=500, default=\"\", blank=True)\n test_fk = models.ForeignKey(\n ConfigurableWidgetsExampleFKModel,\n verbose_name=\"Test FK\",\n on_delete=models.SET_NULL,\n null=True\n )\n test_m2m = models.ManyToManyField(\n ConfigurableWidgetsExampleM2MModel,\n verbose_name=\"Test M2M\"\n )\n\n class Meta:\n verbose_name = \"Configurable widgets example model\"\n verbose_name_plural = \"Configurable widgets example models\"\n\n # ==================\n # project/admin.py\n # ==================\n from admin_toolkit.admin_mixins import ConfigurableWidgetsAdminMixin\n\n\n @admin.register(app_models.ConfigurableWidgetsExampleModel)\n class ConfigurableWidgetsExampleModelAdmin(ConfigurableWidgetsAdminMixin, admin.ModelAdmin):\n list_display = (\"id\", \"test_text\",)\n fieldsets = (\n (None, {\"fields\": (\n (\"test_text\",),\n (\"test_fk\", \"test_m2m\",),\n )}),\n )\n filter_horizontal = (\"test_m2m\",)\n dbfield_overrides = {\n \"test_text\": {\"help_text\": \"Test Text Example help text\", \"widget\": forms.Textarea},\n }\n fkfield_overrides = {\n \"test_fk\": {\"help_text\": \"Test FK Example help text\", \"widget\": forms.RadioSelect},\n }\n m2mfield_overrides = {\n \"test_m2m\": {\"help_text\": \"Test M2M Example help text\", \"widget\": forms.CheckboxSelectMultiple}\n }\n\nThis is the final result:\n\n.. image:: docs/readme_images/configurable_widgets_changeform.png\n :alt: Configurable Widgets Mixin change form Image.\n\n\nDetailInInlineAdminMixin\n________________________\n\nThis admin mixin allows you to have in each line of the inline a button that redirects to the change form of the element created.\n\n.. code-block:: python\n\n from admin_toolkit.admin_mixins import DetailInInlineAdminMixin\n\n\n class DetailInInlineExampleModelAdminInline(DetailInInlineAdminMixin, admin.TabularInline):\n fields = (\"test_text\",)\n model = app_models.DetailInInlineExampleModel\n\nThis is the final result:\n\n.. image:: docs/readme_images/detail_in_inline_changeform.png\n :alt: Configurable Widgets Mixin change form Image.\n\n\nEmptyValueAdminMixin\n____________________\n\nThis admin mixin allows you to define a label for a foreign key field for the empty value.\n\n.. code-block:: python\n\n @admin.register(app_models.EmptyValueExampleModel)\n class EmptyValueExampleModelAdmin(EmptyValueAdminMixin, admin.ModelAdmin):\n list_display = (\"id\", \"test_text\", \"test_fk\",)\n fields = (\"test_text\", \"test_fk\")\n empty_values = {\n \"test_fk\": _(\"NO TEST FK\")\n }\n\nThis is the final result:\n\n.. image:: docs/readme_images/empty_value_change_form.png\n :alt: Empty value admin mixin change form Image.\n\n\nExtraButtonAdminMixin\n_____________________\n\nThis admin mixin allows you to add extra buttons links next to the add button in a simple and immediate way.\n\n.. code-block:: python\n\n @admin.register(app_models.ExtraButtonExampleModel)\n class ExtraButtonExampleModelAdmin(ExtraButtonAdminMixin, admin.ModelAdmin):\n list_display = (\"id\", \"test_text\")\n fields = (\"test_text\",)\n extra_button = [\n {\n \"label\": \"Example Extra Button\",\n \"url\": \"http://example.com\",\n \"class\": \"\"\n }\n ]\n\nThis is the final result:\n\n.. image:: docs/readme_images/extra_button_changelist.png\n :alt: Extra button admin mixin changelist Image.\n\n\nFloatingAdminMixin\n__________________\n\nThis mixin makes the list filters collapsible vertically\nin such a way as to have more space for any columns that otherwise would not be seen.\n\n.. code-block:: python\n\n @admin.register(app_models.FloatingExampleModel)\n class FloatingExampleModelAdmin(FloatingAdminMixin, admin.ModelAdmin):\n list_display = (\"id\", \"test_text\")\n list_filter = (\"test_text\",)\n fields = (\"test_text\",)\n\n\nThis is the final result:\n\n\n#. When the list filter is collapsed.\n .. image:: docs/readme_images/floating_changelist_collapsed.png\n :alt: Floating admin mixin collapsed in changelist Image.\n\n#. When the list filter is decollapsed.\n .. image:: docs/readme_images/floating_changelist_decollapsed.png\n :alt: Floating admin mixin decollapsed in changelist Image.\n\n\nImprovedRawIdFieldsAdminMixin\n_____________________________\n\nThis admin mixin allows you to view the link of the changelist/changeform\nof the selected objects inside the raw_id_field on ForeignKey and ManyToMany.\n\n.. code-block:: python\n\n @admin.register(app_models.ImprovedRawIdFieldsExampleModel)\n class ImprovedRawIdFieldsExampleModelAdmin(ImprovedRawIdFieldsAdminMixin, admin.ModelAdmin):\n improved_raw_id_fields = [\"test_fk\", \"test_m2m\"]\n list_display = (\"id\", \"test_name\",)\n fieldsets = (\n (None, {\"fields\": (\n (\"test_name\",),\n (\"test_fk\", \"test_m2m\"),\n )}),\n )\n\n\nThis is the result:\n\n\n#. When adding an object.\n .. image:: docs/readme_images/improve_raw_fields_changeform_add.png\n :alt: Improve Raw Id Fields admin mixin in changeform add Image.\n\n\n#. When changing an object.\n .. image:: docs/readme_images/improve_raw_fields_changeform_change.png\n :alt: Improve Raw Id Fields admin mixin in changeform change Image.\n\n\nADMIN FILTERS\n_____________\nThis package also comes with a set of list filters\nthat you can use to make it easier to write filters with special queries.\n\n\n.. image:: docs/readme_images/admin_filters_changelist.png\n :alt: Admin filters changelist Image.\n\nCustomRelatedSelectFilter\n=========================\nUsing this filter on Many to Many or Foreign Key it is possible\nto have a list of elements associated with the field inserted in the list_filter\nwhich becomes a select if the list exceeds 4 elements ordered according to a specific\nfield of the foreign key or many to many.\n\n.. code-block:: python\n\n class CustomRelatedSelectFilterForTestFK(admin_filters.CustomRelatedSelectFilter):\n\n def get_related_order(self):\n return [\"test_char\"]\n\n\n class CustomRelatedSelectFilterForTestM2M(admin_filters.CustomRelatedSelectFilter):\n\n def get_related_order(self):\n return [\"test_char\"]\n\n @admin.register(app_models.AdminFilterExampleModel)\n class AdminFilterExampleModelAdmin(admin.ModelAdmin):\n list_display = (\"id\", \"test_char\", \"get_test_choice_display\", \"test_fk\")\n list_filter = (\n (\"test_fk\", CustomRelatedSelectFilterForTestFK),\n (\"test_m2m\", CustomRelatedSelectFilterForTestM2M),\n )\n fieldsets = (\n (None, {\"fields\": (\n (\"test_char\", \"test_choice\", \"test_fk\", \"test_m2m\"),\n )}),\n )\n\n\nThis are the results:\n\n* For the field test_fk:\n\n .. image:: docs/readme_images/admin_custom_related_filter_fk.png\n :alt: Admin custom related filter for FK\n\n\n* For the field test_m2m:\n\n .. image:: docs/readme_images/admin_custom_related_filter_m2m.png\n :alt: Admin custom related filter for M2M\n\n\nRelatedSelectFilter\n===================\nUsing this filter on Many to Many or Foreign Key it is possible\nto have a list of elements associated with the field inserted in the list_filter\nwhich becomes a select if the list exceeds 4 elements.\n\n.. code-block:: python\n\n @admin.register(app_models.AdminFilterExampleModel)\n class AdminFilterExampleModelAdmin(admin.ModelAdmin):\n list_display = (\"id\", \"test_char\", \"get_test_choice_display\", \"test_fk\")\n list_filter = (\n (\"test_fk\", RelatedSelectFilter),\n )\n fieldsets = (\n (None, {\"fields\": (\n (\"test_char\", \"test_choice\", \"test_fk\", \"test_m2m\"),\n )}),\n )\n\n\nSelectFilter\n============\nThis filter can be used on fields that contain choices to be able to display them in a select instead of seeing a bulleted list.\n\n.. code-block:: python\n\n @admin.register(app_models.AdminFilterExampleModel)\n class AdminFilterExampleModelAdmin(admin.ModelAdmin):\n list_display = (\"id\", \"test_char\", \"get_test_choice_display\", \"test_fk\")\n list_filter = (\n (\"test_choice\", SelectFilter),\n )\n fieldsets = (\n (None, {\"fields\": (\n (\"test_char\", \"test_choice\", \"test_fk\", \"test_m2m\"),\n )}),\n )\n\n\nThis is the result:\n\n.. image:: docs/readme_images/admin_select_filter.png\n :alt: Admin select filter for choices Image.\n\n\nSimpleBooleanListFilter\n=======================\nThis filter can be used to give a given query a boolean filter like this example:\n\n.. code-block:: python\n\n # tests/example/admin_filters.py\n\n class SimpleBooleanTestInTestCharFilter(admin_filters.SimpleBooleanListFilter):\n title = \"Test word is in Test char?\"\n parameter_name = \"test_char\"\n\n def get_true_queryset_values(self, queryset):\n return queryset.filter(test_char__icontains=\"test\")\n\n def get_false_queryset_values(self, queryset):\n return queryset.exclude(test_char__icontains=\"test\")\n\n # tests/example/admin.py\n\n from tests.example import admin_filters as app_admin_filters\n\n @admin.register(app_models.AdminFilterExampleModel)\n class AdminFilterExampleModelAdmin(admin.ModelAdmin):\n list_display = (\"id\", \"test_char\", \"get_test_choice_display\", \"test_fk\")\n list_filter = (\n app_admin_filters.SimpleBooleanTestInTestCharFilter,\n )\n fieldsets = (\n (None, {\"fields\": (\n (\"test_char\", \"test_choice\", \"test_fk\", \"test_m2m\"),\n )}),\n )\n\n\nThis is the result:\n\n.. image:: docs/readme_images/admin_boolean_filters.png\n :alt: Admin boolean filter Image.\n\nRunning Tests\n-------------\n\nDoes the code actually work?\n\n::\n\n source <YOURVIRTUALENV>/bin/activate\n (myenv) $ pip install tox\n (myenv) $ tox\n\n\nDevelopment commands\n---------------------\n\n::\n\n pip install -r requirements_dev.txt\n invoke -l\n\n\nCredits\n-------\n\nTools used in rendering this package:\n\n* Cookiecutter_\n* `cookiecutter-djangopackage`_\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`cookiecutter-djangopackage`: https://github.com/pydanny/cookiecutter-djangopackage\n\n\n\n\nHistory\n-------\n\n0.1.0 (2021-11-10)\n__________________\n\n* First release on PyPI.\n\n0.1.1 (2021-11-10)\n__________________\n\n* Fixed HISTORY.rst problems with long_description_content_type\n\n\n0.1.3 (2021-11-10)\n__________________\n\n* Fixed HISTORY.rst problems changing + to _ for versions.\n\n\n0.1.4 (2021-12-6)\n__________________\n\n* Fixed bug on ConfigurableWidgetsAdminMixin.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Multiple admin mixin for yours Django Admins",
"version": "0.1.9",
"project_urls": {
"Homepage": "https://github.com/frankhood/django-admin-toolkit"
},
"split_keywords": [
"django-admin-toolkit"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "fe7004f6f6f35965901cee35e43a5efbaa800def9e4225c070de47f0ae977a51",
"md5": "da4f3af03cc7c80665f9983687b2c06d",
"sha256": "1fee848cb2d2ff00aeda780d2ff788bd70bd75b6ff01a65ca323f80676009819"
},
"downloads": -1,
"filename": "django_admin_toolkit-0.1.9-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "da4f3af03cc7c80665f9983687b2c06d",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 29252,
"upload_time": "2023-11-07T13:38:04",
"upload_time_iso_8601": "2023-11-07T13:38:04.420841Z",
"url": "https://files.pythonhosted.org/packages/fe/70/04f6f6f35965901cee35e43a5efbaa800def9e4225c070de47f0ae977a51/django_admin_toolkit-0.1.9-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "cd4e63b77caf81bde4dabaf883b39874e708ed56fdadb8093efc684c97527e49",
"md5": "62acdae2cbb868c3f2c850bc6a9e3eca",
"sha256": "bcc32eb664120967213e85771e2262486094ebf5d696b635444088954b5e7385"
},
"downloads": -1,
"filename": "django-admin-toolkit-0.1.9.tar.gz",
"has_sig": false,
"md5_digest": "62acdae2cbb868c3f2c850bc6a9e3eca",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 35249,
"upload_time": "2023-11-07T13:38:06",
"upload_time_iso_8601": "2023-11-07T13:38:06.062686Z",
"url": "https://files.pythonhosted.org/packages/cd/4e/63b77caf81bde4dabaf883b39874e708ed56fdadb8093efc684c97527e49/django-admin-toolkit-0.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-07 13:38:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "frankhood",
"github_project": "django-admin-toolkit",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "django-admin-toolkit"
}