diff --git a/CHANGELOG.md b/CHANGELOG.md index 50e3d4f..917ca88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Feature * Drop support for GET method. All action are now invoked with POST method. +* Add option to include inline forms with actions. ### Breaking * When dealing with a secondary form in action, you cannot simply check the http method to determine if the form should be rendered or processed. You need to check for specific form inputs in POST payload. diff --git a/README.md b/README.md index da479d0..9f826aa 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,25 @@ increment_vote.attrs = { } ``` +## Adding inline forms + +You can add parameters to the action button by adding Django [Form](https://docs.djangoproject.com/en/4.1/ref/forms/api/#django.forms.Form) object to it. Parameter values can be read form request's `POST` property. + +```python +from django import forms + +class ResetAllForm(forms.Form): + new_value = forms.IntegerField(initial=0) + +def reset_all(self, request, queryset): + new_value = int(request.POST["new_value"]) + queryset.update(value=new_value) +reset_all.form = ResetAllForm() +``` + +Each action with form assigned is rendered in it's own, separate row. + + ### Programmatically Disabling Actions You can programmatically disable registered actions by defining your own diff --git a/django_object_actions/static/django_object_actions/css/style.css b/django_object_actions/static/django_object_actions/css/style.css new file mode 100644 index 0000000..ef40852 --- /dev/null +++ b/django_object_actions/static/django_object_actions/css/style.css @@ -0,0 +1,6 @@ +ul.object-tools.django-object-actions { + margin-top: 0; + padding-top: 16px; + position: relative; + top: -24px; +} diff --git a/django_object_actions/templates/django_object_actions/change_form.html b/django_object_actions/templates/django_object_actions/change_form.html index 846fb7d..b33d787 100644 --- a/django_object_actions/templates/django_object_actions/change_form.html +++ b/django_object_actions/templates/django_object_actions/change_form.html @@ -1,21 +1,56 @@ {% extends "admin/change_form.html" %} {% load add_preserved_filters from admin_urls %} +{% load static %} + +{% block extrastyle %} +{{ block.super }} + +{% endblock %} {% block object-tools-items %} {% for tool in objectactions %} -
  • - {% url tools_view_name pk=object_id tool=tool.name as action_url %} -
    - {% csrf_token %} - - {{ tool.label|capfirst }} - -
    -
  • + {% if not tool.form %} +
  • + {% url tools_view_name pk=object_id tool=tool.name as action_url %} +
    + {% csrf_token %} + + {{ tool.label|capfirst }} + +
    +
  • + {% endif %} {% endfor %} {{ block.super }} {% endblock %} + +{% block object-tools %} + {{ block.super }} + {% for tool in objectactions %} + {% if tool.form %} + {% url tools_view_name pk=object_id tool=tool.name as action_url %} +
    +
    + {% csrf_token %} + +
    +
    + {% endif %} + {% endfor %} +
    +{% endblock %} diff --git a/django_object_actions/templates/django_object_actions/change_list.html b/django_object_actions/templates/django_object_actions/change_list.html index b7c9b80..4e6fba6 100644 --- a/django_object_actions/templates/django_object_actions/change_list.html +++ b/django_object_actions/templates/django_object_actions/change_list.html @@ -1,21 +1,56 @@ {% extends "admin/change_list.html" %} {% load add_preserved_filters from admin_urls %} +{% load static %} + +{% block extrastyle %} +{{ block.super }} + +{% endblock %} {% block object-tools-items %} {% for tool in objectactions %} -
  • - {% url tools_view_name tool=tool.name as action_url %} -
    - {% csrf_token %} - - {{ tool.label|capfirst }} - -
    -
  • + {% if not tool.form %} +
  • + {% url tools_view_name tool=tool.name as action_url %} +
    + {% csrf_token %} + + {{ tool.label|capfirst }} + +
    +
  • + {% endif %} {% endfor %} {{ block.super }} {% endblock %} + +{% block object-tools %} + {{ block.super }} + {% for tool in objectactions %} + {% if tool.form %} + {% url tools_view_name tool=tool.name as action_url %} +
    +
    + {% csrf_token %} + +
    +
    + {% endif %} + {% endfor %} +
    +{% endblock %} diff --git a/django_object_actions/tests/test_admin.py b/django_object_actions/tests/test_admin.py index 8fba3b4..ecbda4b 100644 --- a/django_object_actions/tests/test_admin.py +++ b/django_object_actions/tests/test_admin.py @@ -8,6 +8,7 @@ from .tests import LoggedInTestCase from example_project.polls.factories import ( + ChoiceFactory, CommentFactory, PollFactory, RelatedDataFactory, @@ -134,3 +135,36 @@ def test_redirect_back_from_secondary_admin(self): response = self.client.post(action_url) self.assertRedirects(response, admin_change_url) + + +class FormTests(LoggedInTestCase): + def test_form_is_rendered_in_change_view(self): + choice = ChoiceFactory() + admin_change_url = reverse("admin:polls_choice_change", args=(choice.pk,)) + + response = self.client.get(admin_change_url) + + # form is in the admin + action_url_lookup = 'action="/admin/polls/choice/1/actions/change_votes/"' + self.assertIn(action_url_lookup, response.rendered_content) + form_lookup = '