Search code examples
jquerypythonflaskflask-appbuilder

flask jquery GET 404


I'm playing with jQuery in Flask and have been making use of a simple example I found on runnable of adding two numbers together.

I'm using Flask-Appbuilder and have a view all setup to display the template, which works fine. I included the jQuery code into the template and it displays what it should.

On the Flask side I created the View, and the functions in the view to render the template and to receive the variables in the jQuery GET request.

When I click the jQuery link on the template to add the two number together, I see a 404 error in the python console.

[07/Apr/2017 09:48:53] "GET /_add_numbers?a=1&b=1 HTTP/1.1" 404 -

Here's what I have in my template:

{% extends "appbuilder/base.html" %}

{% block content %}
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
          rel="stylesheet">
  <script type=text/javascript>
    $(function() {
      $('a#calculate').bind('click', function() {
        $.getJSON('/_add_numbers', {
          a: $('input[name="a"]').val(),
          b: $('input[name="b"]').val()
        }, function(data) {
          $("#result").text(data.result);
        });
        return false;
      });
    });
  </script>

  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">How To Manage JSON Requests</h3>
      </div>
      <hr/>
      <div>
      <p>
    <input type="text" size="5" name="a"> +
    <input type="text" size="5" name="b"> =
    <span id="result">?</span>
    <p><a href="javascript:void();" id="calculate">calculate server side</a>
      </form>
      </div>
    </div>
  </body>
</html>
{% endblock %}

My flask view looks like this:

class MyView(BaseView):
    default_view = 'sale'

    @expose('/sale', methods=['GET'])
    @has_access
    def sale(self):
        return self.render_template('sale.html')

    @expose('/_add_numbers', methods=['GET', 'POST'])
    @has_access
    def add_numbers(self):
        a = request.args.get('a', 0, type=int)
        b = request.args.get('b', 0, type=int)
        return jsonify(result=a + b)

Any guidance would be much appreciated.

GET Screenshot - https://i.sstatic.net/cN4wg.jpg

POST Screenshot - https://i.sstatic.net/lJC1Q.jpg


Solution

  • You are using flask-appbuilder and the syntax suggested is:

    class MyView(BaseView):
        route_base = "/myview"
    
        @expose('/method1/<string:param1>')
        def method1(self, param1):
            # do something with param1
            # and return it
            return param1
    

    Which results in a url looking like this: http://<your_host>/myview/method1/<awaiting string param>

    That is probably what interferes with your URL.


    A bit more thorough explanation:

    GET request tries to locate the /_add_numbers?a=1&b=1 URL which as far as your back-end is concerned does not match any exposed URL.
    You should try defining your exposed URL as follows:

    @expose('/_add_numbers?<int:a>&<int:b>', methods=['GET', 'POST']) 
    

    If flask-appbuilder gives you problems, try to experiment with the default flask and see if that works for you, then with that knowledge move forward.


    Note:

    Typically this is not a GET but a POST request.

    You can try a simple jquery $.post() call instead of getJSON:

    $.post('http://localhost:5000/_add_numbers',{
        a: $('input[name="a"]').val(),
        b: $('input[name="b"]').val()
    }, function(data) {
        $("#result").text(data.result);
    });
    

    The No 'Access-Control-Allow-Origin' header is present on the requested resource. error has been referred and answered thoroughly in those posts: