Additional action button doesn't work on flask-admin

Viewed 2404

I'm trying to add one more action to flask-admin forms.

enter image description here

It has to increment rating (+1) and it works with batch action, but not with single. Please help me find the bug, I've spent a lot of time trying to make this thing work properly.

Here's the code:

I made an html template in templates folder - custom_lists.html

{% extends 'admin/model/list.html' %}
{% block list_row_actions %}
    {{ super() }}
  <form class="icon" method="POST" action="/admin/user/action/">
    <input id="action" name="action" value="approve" type="hidden">
    <input name="rowid" value="{{ get_pk_value(row) }}" type="hidden">
    <button onclick="return confirm('Are you sure you want to approve selected items?');" title="Approve">
      <span class="fa fa-ok glyphicon glyphicon-ok"></span>
    </button>
  </form>
{% endblock %}

this succeeded with an icon on the list, but if i click to it - it says

Not Found

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

added to templates folder and added to AdidasView class this:

list_template = 'custom_list.html'
@action('approve', 'Approve', 'Are you sure you want to approve selected items?')
def action_approve(self, ids):
    try:
        query = Adidas.query.filter(Adidas.id.in_(ids))

        count = 0
        for image in query.all():
            image.rating += 1
            count += 1
            db.session.commit()
        flash(ngettext('Item was successfully approved.',
                       '%s items were successfully approved.'%count,count))
    except Exception as ex:
        if not self.handle_view_exception(ex):
            raise

        flash(gettext('Failed to approve items. %(error)s', error=str(ex)), 'error')
2 Answers

I have not changed the template but I have done it differently as following by setting the column_extra_row_actions variable and defining the action_play function

column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon glyphicon-play', 'event.action_play')
    ]

@expose('/action/play', methods=('GET',))
def action_play(self, *args, **kwargs):
    return self.handle_action()

This solution does not seem to apply to this example, but I also struggled with a case where I received a 404 when I using an action on one item via the button, while the batch action worked as expected.

After taking a look at the JS for the batch action I realized that the two HTML forms for individual actions and batch actions are practically identical. The only difference is that when using batch actions there may be more input fields in the form. That implies that if you get a 404 on one, but not the other, there must be an error in your HTML.

In my case I was not aware that Flask-Admin addresses models_with_underscores_in_their_name as modelswithunderscoresintheirname. Therefore instead of

<form class="icon" method="POST" action="/admin/mymodel/action/">

my erroneous code was

<form class="icon" method="POST" action="/admin/my_model/action/">

Note the difference in the action field.

With this change I was able to use the @action API as explained in the Flask-Admin docs.

Related