2

i have this Model Admin:

class Items(admin.ModelAdmin)

    actions = ['action_create_task']

    def action_create_task(self, request, queryset):
        if request.POST.get('post'):
            form = CreateTaskAction(request.POST)

            if form.is_valid():
                # doing something
                self.message_user(request, "Success appended task!")
                return redirect(request.get_full_path())
        else:
            form = CreateTaskAction()

        return render(request, 'create_task.html', {
            'title': 'Create task for selected items',
            'itmes': queryset,
            'form': form
        })

And i use this HTML code on my template create_task.html

{% extends "admin/base_site.html" %}

{% block content %}

    {% load staticfiles %}

    <form action="" method="post">
        {% csrf_token %}

        {{ form }}

        <h2>Create task for this items</h2>
        <ul>{{ items|unordered_list }}</ul>

        <input type="hidden" name="action" value="action_create_task" />
        <input type="hidden" name="post" value="yes" />
        <input type="submit" value="Create task" />
    </form>
{% endblock %}

But if i select some items, next select action and then submit Create Task Action form, i haven't receive any POST and will just redirected to list of objects without something messages and etc. In other words, when i submit my form i redirected to sites list, without calling my action function. Whats am i doing wrong?

Patrick Burns
  • 1,763
  • 6
  • 21
  • 35
  • have you specified a url for form action? – Tianwei Chen Jul 23 '15 at 15:11
  • @Sky, no, i show all my code. I really need spicify url? If it is, what url? – Patrick Burns Jul 23 '15 at 15:14
  • Nope, that's fine (after a quick check on html spec). I think you may want to use `if request.method == 'POST'` to test whether it's a post request. Why are you using `if request.POST.get('post')`? – Tianwei Chen Jul 23 '15 at 15:36
  • @Sky, no i cant use `request.method == 'POST'`, because any request with actions requested only with `POST` in this opinion i use (such as in original django admin delete action) hidden input `post=yes`. – Patrick Burns Jul 23 '15 at 15:42

1 Answers1

0

You are writing a more complex admin action that requires intermediate pages. You are mixing your action function and your action view (the intermediate view). When you fire an action, a view provided by django handles it and calls you action function providing selected model instance (the queryset), after that, the calling view redirects user back to original change list page. So you are effective posting the form to the django view that supposed to handle action request, that's why you keep getting refresh redirection.

What you want to do is create a create_task_view:

class Items(admin.ModelAdmin)

    actions = ['action_create_task']

    def action_create_task(self, request, queryset):
        # do some validation on queryset and request
        if all good:
            return HttpResponseRedirect(/path_to_create_task_view)
        else:
            self.message_user('action rejected')

    def create_task_view(self, request):
        if request.method == 'POST':
            form = CreateTaskAction(request.POST)
            if form.is_valid():
                # doing something
                self.message_user(request, "Success appended task!")
                return HttpResponseRedirect(/somewhere)
        else:
            form = CreateTaskAction()

        return render(request, 'create_task.html', {
            'title': 'Create task for selected items',
            'itmes': queryset,
            'form': form
        })

Note you may want to avoid hard-coded urls, see reverse resolution of URLS. Also see actions that provides intermediate pages.

Tianwei Chen
  • 148
  • 11