You've already forked django-changelist-inline
Public release
This commit is contained in:
201
README.rst
Normal file
201
README.rst
Normal file
@@ -0,0 +1,201 @@
|
||||
========================
|
||||
django-changelist-inline
|
||||
========================
|
||||
|
||||
Inline Changelists for Django
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Django Admin comes with inlines_ which allows you to display forms to edit
|
||||
related objects from the parent object's change form. While it's technically
|
||||
possible to use this infrastructure to display list of related objects, it
|
||||
gets hacky pretty fast.
|
||||
|
||||
Here's where *django-changelist-inline* comes into play. It allows you to embed
|
||||
the standard list of objects as an inline on the parent object's change form.
|
||||
Internally, it uses a subclass of ``ModelAdmin``, which means you can customize
|
||||
the list as you'd normally do. Additionally, you can display links below the
|
||||
list of objects.
|
||||
|
||||
Usage Example
|
||||
=============
|
||||
|
||||
Let's assume you have a Django project with two models - ``Thing`` and
|
||||
``RelatedThing`` and that you want to display list of ``RelatedThing`` objects
|
||||
as an inline in ``Thing`` change form. The follwing snippet provides an example
|
||||
of how to implement that using *django-changelist-inline*:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.contrib import admin
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django_changelist_inline import (
|
||||
ChangelistInline,
|
||||
ChangelistInlineAdmin,
|
||||
ChangelistInlineModelAdmin,
|
||||
)
|
||||
|
||||
from testing.models import RelatedThing, Thing
|
||||
|
||||
|
||||
@admin.register(RelatedThing)
|
||||
class RelatedThingModelAdmin(admin.ModelAdmin):
|
||||
list_display = ('pk', 'name')
|
||||
|
||||
|
||||
class RelatedThingChangelistInline(ChangelistInline):
|
||||
model = RelatedThing
|
||||
|
||||
class ChangelistModelAdmin(ChangelistInlineModelAdmin):
|
||||
list_display = ('name', 'format_actions')
|
||||
list_display_links = None
|
||||
list_per_page = 5
|
||||
|
||||
def get_queryset(self, request):
|
||||
return RelatedThing.objects.filter(thing=self.parent_instance)
|
||||
|
||||
@mark_safe
|
||||
def format_actions(self, obj=None):
|
||||
if obj is None:
|
||||
return self.empty_value_display
|
||||
|
||||
change_link_url = reverse(
|
||||
'admin:{app_label}_{model_name}_change'.format(
|
||||
app_label=RelatedThing._meta.app_label,
|
||||
model_name=RelatedThing._meta.model_name,
|
||||
),
|
||||
args=[obj.pk],
|
||||
)
|
||||
|
||||
return (
|
||||
f'<a class="button" href="{change_link_url}">'
|
||||
'Edit'
|
||||
'</a>'
|
||||
)
|
||||
format_actions.short_description = 'Actions'
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return 'Linked Related Things'
|
||||
|
||||
@property
|
||||
def no_results_message(self):
|
||||
return 'No Related Things?'
|
||||
|
||||
def get_add_url(self, request):
|
||||
result = super().get_add_url(request)
|
||||
if result is not None:
|
||||
return result + '?' + urlencode({
|
||||
'thing': self.parent_instance.pk,
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def get_show_all_url(self, request):
|
||||
result = super().get_show_all_url(request)
|
||||
if result is not None:
|
||||
return result + '?' + urlencode({
|
||||
'thing': self.parent_instance.pk,
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def get_toolbar_links(self, request):
|
||||
return (
|
||||
'<a href="https://www.bthlabs.pl/">'
|
||||
'BTHLabs'
|
||||
'</a>'
|
||||
)
|
||||
|
||||
|
||||
@admin.register(Thing)
|
||||
class ThingModelAdmin(ChangelistInlineAdmin):
|
||||
inlines = (RelatedThingChangelistInline,)
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
``ChangelistInline`` objects
|
||||
----------------------------
|
||||
|
||||
The ``ChangelistInline`` class is the center piece of the API. It's
|
||||
designed to be used in a ``ModelAdmin``'s ``inlines``.
|
||||
|
||||
In order for it to work, you'll need to define the ``model`` property and
|
||||
embed ``ChangelistModelAdmin`` class, which should be a subclass of
|
||||
``ChangelistInlineModelAdmin``.
|
||||
|
||||
``ChangelistInlineModelAdmin`` objects
|
||||
--------------------------------------
|
||||
|
||||
The ``ChangelistInlineModelAdmin`` is a customized ``ModelAdmin`` subclass
|
||||
which provides sane defaults and additional functionality for inline
|
||||
changelists.
|
||||
|
||||
**Changelist sanitization**
|
||||
|
||||
This subclass overrides the following attributes and methods of ``ModelAdmin``
|
||||
to provide sane defaults:
|
||||
|
||||
* ``list_editable`` - set to empty tuple to disable editing of the list,
|
||||
* ``list_filter`` - set to empty tuple to disable filtering of the list,
|
||||
* ``search_fields`` - set to empty tuple to disable searching,
|
||||
* ``date_hierarchy`` - set to ``None``,
|
||||
* ``sortable_by`` - set to empty tuple to disable sorting,
|
||||
* ``get_actions()`` - returns empty list to disable actions.
|
||||
|
||||
**Additional functionality**
|
||||
|
||||
To allow customization and to expose additional functionality,
|
||||
``ChangelistInlineModelAdmin`` provides the following additional methods:
|
||||
|
||||
* ``title`` property - returns the model's *verbose name* by default.
|
||||
* ``no_results_message`` property - returns text to display in place of the
|
||||
table if no objects are fetched from the DB.
|
||||
* ``get_add_url(request)`` - returns URL for the model's add form, if the
|
||||
user has the add permission. Return ``None`` to hide the add link.
|
||||
* ``get_show_all_url(request)`` - returns URL for the model's changelist, if
|
||||
the user has the view permission. Return ``None`` to hide the show all link.
|
||||
* ``get_toolbar_links(request)`` - returns ``None`` by default. Override this
|
||||
to return string with additional ``<a/>`` elements to render in the toolbar.
|
||||
The return value is marked safe in the template.
|
||||
|
||||
``ChangelistInlineAdmin`` objects
|
||||
---------------------------------
|
||||
|
||||
The ``ChangelistInlineAdmin`` class is a base class for ``ModelAdmin``
|
||||
subclasses that use inline changelists.
|
||||
|
||||
``ChangelistInlineAdminMixin``
|
||||
------------------------------
|
||||
|
||||
A mixin class that is used to properly configure changelist inlines in the
|
||||
parent ``ModelAdmin``. Overrides ``get_inlines(request, obj=None)`` and
|
||||
``get_inline_instances(request, obj=None)`` methods.
|
||||
|
||||
If you can't use ``ChangelistInlineAdmin`` as you base class, you can use this
|
||||
mixin to enable inline changelists:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@admin.register(Thing)
|
||||
class ThingModelAdmin(ChangelistInlineAdminMixin, MyBaseModelAdmin):
|
||||
...
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
*django-changelist-inline* is developed by `Tomek Wójcik`_.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
*django-changelist-inline* is licensed under the MIT License.
|
||||
|
||||
.. _inlines: https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#inlinemodeladmin-objects
|
||||
.. _Tomek Wójcik: https://www.bthlabs.pl/
|
||||
Reference in New Issue
Block a user