John Hunter
John Hunter

Reputation: 33

Posting JSON to flask template

I've been banging my head against a wall trying to work out how to firstly get JSON data returned from my search (which I've now solved thankfully) and to then update my jinja template with the JSON data spewed out.

I've tried a few methods but I seem to be going around in circles and as I'm not very experienced with either AJAX or Flask I tend to cause more problems than I can fix.

I have an AJAX file but I don't believe it is working (if it is even correct) but I'm guessing that this needs to be instructed to take the data and put it into the correct table/area of the rendered template? my question is how can I make this happen?

Below is my app.py

from flask import request, jsonify
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
from flask import render_template
from sqlalchemy import create_engine
from flask_marshmallow import Marshmallow
import json

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='postgresql://postgres:test@localhost/postgres'
engine = create_engine('postgresql+psycopg2://postgres:test@localhost/postgres')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

app.debug = True
app.config['SQLALCHEMY_ECHO'] = True
db=SQLAlchemy(app)
Bootstrap(app)
ma=Marshmallow(app)
# classes

class Sdctest(db.Model):
    startchass= db.Column (db.Text, primary_key=True)
    cusname= db.Column (db.Text)
    chassistype1= db.Column (db.Text)
    axleqty= db.Column (db.Integer)
    tyres= db.Column (db.Text)
    extlength= db.Column (db.Text)
    neck= db.Column (db.Text)
    stepheight= db.Column (db.Text)
    reardeckheight= db.Column (db.Text)
    siderave= db.Column (db.Text)
    steer= db.Column (db.Text)
    sockets= db.Column (db.Text)
    containerstwistlock= db.Column (db.Text)
    headboard= db.Column (db.Text)





class TableSchema(ma.Schema):
    class Meta:
        fields = ('startchass', 'cusname', 'chassistype1', 'axleqty', 'tyres', 'extlength', 'neck', 'stepheight', 'reardeckheight', 'siderave', 'steer', 'sockets', 'containerstwistlock', 'headboard')
tables = TableSchema()
tabless = TableSchema(many=True)

#routes
@app.route('/')

def index():

        return render_template('index.html')

@app.route('/platform', methods=['GET', 'POST'])

def curtainsider():
    options = db.session.query(Sdctest.chassistype1).distinct().all()
    axleopts = db.session.query(Sdctest.axleqty).distinct().all()
    # enables passing user input to the variable
    if request.method == 'POST':
        # query parameters and their corresponding database columns
        param_columns = {
            "startchass": "startchass",
            "cusname": "cusname",
            "chassistype1": "chassistype1",
            "axleqty": "axleqty",
            "tyres": "tyres",
            "siderave": "siderave",
            "steer": "steer",
            "sockets": "sockets",
            "containerstwistlock":"containerstwistlock",
            "headboard": "headboard",

        }
        param_column2 = {
            "startchass": "startchass",
            "extlength": "extlength",
            "neck": "neck",
            "stepheight": "stepheight",
            "reardeckheight": "reardeckheight",

        }
        # Get all of the column filters where the parameters aren't empty

        filters = {
            column: request.form[param]
            for param, column in param_columns.items()
            if request.form.get(param, "") != ""
        }
        filters2 = {
            column: request.form[param]
            for param, column in param_column2.items()
            if request.form.get(param, "") != ""
        }
        #filter most columns using fuzzy match
        query = Sdctest.query
        for column, value in filters.items():
            query = query.filter(getattr(Sdctest, column).ilike(f'%{value}%')) .order_by(Sdctest.startchass.desc())
        for column, value in filters2.items():
            query = query.filter(getattr(Sdctest, column).ilike(f'{value}')).order_by(Sdctest.startchass.desc())
        results2 = query.all()
        result2 = tabless.dump(results2, object)
        # renders the template
        return render_template('platform.html')
        return jsonify(result2)

    else:
        return render_template('platform.html', options=options)

    if __name__ == "__main__":
        run_server()`

and this is my template:

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <style>
        body {
  padding: 15px;
                background-image: url("/static/bg.png");
    background-repeat: no-repeat;
}
.table-hideable td,
.table-hideable th {
  width: auto;
  transition: width .5s, margin .5s;

}
.btn-condensed.btn-condensed {
  padding: 0px 0px 0px 0px;
  box-shadow: none;
}
.hide-col {
    width: 0 !important;
    height: 0 !important;
    display: none !important;
    overflow: hidden !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
}
.thbg
{
    background-image: url("/static/fieldbg.png");
}
.thbgg
{
    background-color:#b21f2d ;
    color: #FFF;
}
    </style>

<link rel="stylesheet" href={{ url_for('static', filename='css/bootstrap.css') }}>
<script defer src="https://use.fontawesome.com/releases/v5.0.13/js/all.js" integrity="sha384-xymdQtn1n3lH2wcu0qhcdaOpQwyoarkgLVxC/wZ5q7h9gHtxICrpcaSUfygqZGOe" crossorigin="anonymous"></script>
    <meta charset="UTF-8">
    <title>Sales Search</title>

</head>
<body>
<div id="wrapper">
<div class="corner-ribbon top-left red shadow">ALPHA</div>
<div align="center" class="p"><img src="/static/sdclogopng.png"> </div>
<div class="container-fluid" id="container-fluid">
<div class="row">
<div class="col-sm-9">
<div class="form-group">
<form method="POST" class="form-horizontal" role="form" name="form" id="form">
    <div class="form-row form-group">
   <div class="col-auto">
    <input type="text" name="startchass" class="form-control form-control-sm thbg" placeholder="Chassis Number">
    </div>
    <div class="col-auto">
    <input type="text" name="cusname" class="form-control form-control-sm thbg" placeholder="Customer name">
    </div>

    <div class="col-auto">
    <select name="chassistype1" class="form-control form-control-sm thbg" title="chassis type">
        <option disabled selected value>Select chassis type</option>
        {% for option in options %}
    <option class="form-control form-control-sm thbg" value="{{ option[0] }}">{{ option[0] }}</option>
        {% endfor %}
  </select>
</div>
    <div class="col-auto">
    <select name="axleqty" class="form-control form-control-sm thbg" title="chassis type">
      <option disabled selected value>Axle quantity</option>
        {% for axleopt in axleopts %}
    <option class="form-control form-control-sm thbg" value="{{ axleopt[0] }}">{{ axleopt[0] }}</option>
        {% endfor %}
  </select>
</div>


        <div class="col-auto">
    <input type="text" name="tyres" class="form-control form-control-sm thbg" placeholder="tyre type" id="1">
    </div></div>
<div class="form-row form-group">
    <div class="col-auto">
   <input type="text" name="extlength" class="form-control form-control-sm thbg" placeholder="External Length" id="2">
    </div>

     <div class="col-auto">
   <input type="text" name="neck" class="form-control form-control-sm thbg" placeholder="Neck Dimensions" id="3">
     </div>

     <div class="col-auto">
   <input type="text" name="stepheight" class="form-control form-control-sm thbg" placeholder="Step height" id="3">
</div>
     <div class="col-auto">
   <input type="text" name="reardeckheight" class="form-control form-control-sm thbg" placeholder="reardeckheight" id="4">
    </div>

     <div class="col-auto">
   <input type="text" name="siderave" class="form-control form-control-sm thbg" placeholder="Siderave" id="5">
     </div></div>
<div class="form-row form-group">
     <div class="col-auto">
   <input type="text" name="steer" class="form-control form-control-sm thbg" placeholder="Steer option" id="6">
    </div>

     <div class="col-auto">
   <input type="text" name="sockets" class="form-control form-control-sm thbg" placeholder="Socket count" id="7">
    </div>

    <div class="col-auto">
   <input type="text" name="containertwistlock" class="form-control form-control-sm thbg" placeholder="Twist locks" id="8">
    </div>

    <div class="col-auto">
   <input type="text" name="headboard" class="form-control form-control-sm thbg" placeholder="headboard" id="9">
    </div>

 <input type="submit" value="Search" class="btn btn-danger btn-sm" id="button" name="button" type="button"></div>
    </form>
</div></div><div class=col-sm-3> <div class="refinewidth">   <h6 style="color:#fff">search for specific items/text here:</h6>
    <input class="form-control form-control-sm thbg" id="myInput" type="text" placeholder="Search.."></div><br></div></div></div>

<div class="col-sm-4 alert alert-info"><strong>Click on a column header to exclude it from your results</strong></div>

{% block body %}

    <div class="table-responsive">

<table class="table table-condensed table-hover table-bordered table-hideable table-sm">
  <thead class="table-hideable thbgg">
    <tr>
      <th class="hide-column">Chassis Number </th>

      <th class="hide-column">Customer name</th>

      <th class="hide-column">Chassis Type</th>

        <th class="hide-column">Axles</th>

        <th class="hide-column">Tyre</th>

        <th class="hide-column">External Length</th>

        <th class="hide-column">Neck</th>

        <th class="hide-column">Step height</th>

        <th class="hide-column">Rear Deck height</th>

        <th class="hide-column">Siderave</th>

        <th class="hide-column">Steer</th>

        <th class="hide-column">Sockets</th>

        <th class="hide-column">Twistlocks</th>

        <th class="hide-column">Headboard</th>

    </tr>
  </thead>
<tbody id="myTable">
{% for item in result2 %}
  <tr>
<td class>{{ item.startchass }}</td><td>{{ item.cusname }}</td><td>{{ item.chassistype1 }}<td>{{ item.axleqty }}</td><td>{{ item.tyres }}</td><td>{{ item.extlength }}</td><td>{{ item.neck }}</td><td>{{ item.stepheight }}</td><td>{{ item.reardeckheight }}</td><td>{{ item.siderave }}</td><td>{{ item.steer }}</td><td>{{ item.sockets }}</td><td>{{ item.containerstwistlock }}</td><td>{{ item.headboard }}</td>
      </tr>
  {% endfor %}
</tbody>

<tfoot class="show-column-footer">
    <tr>
      <th colspan="14"><a class="show-column" href="#">Click here to show hidden columns</a></th>
    </tr>
</tfoot>
      </table>

</div>

{% endblock %}
<script>
$(document).ready(function(){
  $("#myInput").on("keyup", function() {
    var value = $(this).val().toLowerCase();
    $("#myTable tr").filter(function() {
      $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
    });
  });
});
</script>
<script type=text/javascript src="{{ url_for('static', filename='ajax.js') }}"></script>
<script type=text/javascript src="{{ url_for('static', filename='form.js') }}"></script>
</div>
</body>
</html>

and lastly my (probably not working) AJAX file:

$(function() {
$('form').on('submit', function(e){
        $.ajax({
            url: '/platform',
            data: $('form').serialize(),
            type: 'POST',
            cusname:cusname,
            success: function(response) {
                console.log(response);
            },
            error: function(error) {
                console.log(error);
            }
        });
    });
});

Upvotes: 0

Views: 1439

Answers (1)

Jessi
Jessi

Reputation: 1468

I don't fully understand what you are trying to achieve but I'm guessing you try to take the search box inputs and use those to query the DB and return JSON into the table? If this is not what you try to achieve, please answer four questions that I've commented above. Also, I strongly recommend you use some sort of validation in your search box since it is directly going into your query (DB). You can use Flask-WTF(server side form validation- better) or even a client side form validation library (weaker).

Considering above is the case for you, below is the minimized example.

Ajax

$(function() {
// please do not use form as an ID as this may be a potential error later on.
$('#form').on('submit', function(e){
        $.ajax({
            url: '/platform', //not a good practice to use /platform, but instead use "{{url_for('.curtainsider')}}"
            data: $('form').serialize(), //removed cusname, if you need to pass cusname into the server, create a hidden input field and include it inside <form></form>
            type: 'POST',
            success: function(response) {
                var dbData = response.result;
                // do your thing here with the data that was passed from curtainsider()
            },
            error: function(error) {
                console.log(error);
            }
        });
    });
});

View

@app.route('/platform', methods=['GET', 'POST'])
def curtainsider():
    # to parse the serialized form.
    if request.method == 'POST':
        data_one = request.form['data_one']
        cusname = request.form['cusname']
        # and so on....
        # make DB queries based on your input
        return jsonify({'result': db_data})

Below is when it is CSRF protected.

If your form is CSRF protected, attach below code to the end of ajax function. And also include {{form.csrf_token}} inside your form element in HTML.

$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", "{{ form.csrf_token._value() }}")
        }
    }
});

Upvotes: 1

Related Questions