diff --git a/django_adminlink/admin.py b/django_adminlink/admin.py index ae36a75..50054f2 100644 --- a/django_adminlink/admin.py +++ b/django_adminlink/admin.py @@ -11,6 +11,11 @@ class LinkFieldAdminMixin: admin_url_namespace = "admin" def _convert_list_display_item(self, field_name): + """ + Converts a list display field name to a callable that renders a link for ForeignKey fields. + + If the specified field is a ForeignKey, returns a callable that displays the related object as a clickable link to its admin change page. Otherwise, returns the original field name. + """ if isinstance(field_name, str): try: field = self.model._meta.get_field(field_name) @@ -30,6 +35,11 @@ def get_list_display(self, request): return result def _link_to_model_field(self, field): + """ + Returns a callable that renders a ForeignKey field as a clickable link to the related object's admin change page. + + If the related model is not registered with the admin site, returns the field name instead. + """ related_model = field.related_model admin_site = self.admin_site_to_link or admin.site model_admin = admin_site._registry.get(related_model) @@ -41,6 +51,15 @@ def _link_to_model_field(self, field): @admin.display(description=field.name, ordering=f"{field.name}") def column_render(obj): + """ + Renders a foreign key field as a clickable link to the related object's admin change page. + + Args: + obj: The model instance containing the foreign key field. + + Returns: + An HTML anchor element linking to the related object's admin page, or None if the field is not set. + """ key = getattr(obj, field.name) if key is not None: return format_html( @@ -65,6 +84,12 @@ class SingleItemActionMixin: @admin.display(description="actions") def action_button_column(self, obj): + """ + Renders action buttons for each object in the admin list display. + + Each button is configured with data attributes for the action name and object primary key, + and triggers the `get_checkboxes` JavaScript function when clicked. + """ if isinstance(self.action_buttons, dict): action_buttons = self.action_buttons.items() else: @@ -76,6 +101,12 @@ def action_button_column(self, obj): ) def get_list_display(self, request): + """ + Extends the list display to include a column of action buttons if any are defined. + + If the `action_buttons` attribute is set, appends the `action_button_column` to the list + display; otherwise, returns the default list display. + """ items = super().get_list_display(request) if self.action_buttons: return [*items, self.action_button_column] @@ -85,6 +116,12 @@ def get_list_display(self, request): @property def media(self): + """ + Extends the admin media to include JavaScript for single-item action buttons. + + Returns: + The combined media object with the additional JavaScript file included. + """ return super().media + Media(js=["js/single_admin_action.js"]) diff --git a/django_adminlink/static/js/single_admin_action.js b/django_adminlink/static/js/single_admin_action.js index 08492bc..0b3ee17 100644 --- a/django_adminlink/static/js/single_admin_action.js +++ b/django_adminlink/static/js/single_admin_action.js @@ -1,3 +1,10 @@ +/** + * Selects a single item in a Django admin list and triggers the specified admin action for that item. + * + * Retrieves the primary key and action from the provided element's data attributes, updates the action selector, unchecks all other items, checks the targeted item, and submits the form to perform the action on that item only. + * + * @param {Element} e - The element containing `data-pk` and `data-action` attributes for the target item and action. + */ function get_checkboxes(e) { const pk = e.getAttribute('data-pk'); const action = e.getAttribute('data-action');