0

I have a working flask app set up with a HTML page. The problem is that in my HTML, where I have {{ Appointments }}, it always shows the value of the second render_template, of an empty list.

@app.route("/PatientDashboard.html", methods=["GET", "POST"])
def PatientDashboard():

    if request.method == "POST":
        Date = request.form.get("Date")
        print(Date)
        return render_template("PatientDashboard.html", Appointments=["This should show up."])

    else:
        return render_template("PatientDashboard.html", Appointments=[]) 

The problem is that the first render_template is never expressed. Why is this and how would I solve it?

Thank you ever so much in advance.

EDIT 1:

Relevant HTML is below.

<script>
    var jsDate = $('#calendar').datepicker({
        inline: true,
        firstDay: 1,
        showOtherMonths: false,
        dayNamesMin: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        onSelect: function(dateText, inst) {
            document.getElementById("Date").innerHTML = dateText;
            $.ajax({
                type: 'POST',
                url: "{{ url_for('PatientDashboard') }}",
                data: {Date: dateText},
                dataType: "text",
            });
        }
    });
</script>

Further on I have the {{ Appointments }} in a divider.

nx_prv
  • 127
  • 8
  • Are you sure your form uses the POST method? – Robin Zigmond Feb 18 '19 at 11:45
  • It's not a form but a `$.ajax({ type: 'POST', url: "{{ url_for('PatientDashboard') }}" });` instead. The type is still POST method. – nx_prv Feb 18 '19 at 11:49
  • OK, thanks - I assumed it was a form due to your use of `request.form`. But a `POST` request will definitely land in that `if` block and render the `"This should show up."`. Something else must be going on in your code - can you share the relevant HTML template and Javascript? – Robin Zigmond Feb 18 '19 at 12:12
  • thanks for the update, what stands out to me now is that you have no `success` callback in your ajax, so nothing will happen anyway when you select a date from the datepicker? – Robin Zigmond Feb 18 '19 at 12:26
  • I am not using a callback in my ajax because I can't find a way to manipulate any of the data I get (https://stackoverflow.com/questions/54744456/how-to-manipulate-variables-in-html) so I am using it to pass a variable to flask then processing it there and then retuning a list to the render_template. – nx_prv Feb 18 '19 at 12:32
  • what happens at the moment when you select a date? I'm assuming nothing at all - but please correct me if I'm wrong. What is actually happening is that the Ajax fires and sends a POST request to your Flask backend, which responds with the HTML of the rendered template - but because you don't do anything to handle the response in your Javascript, you won't see any visible change. You can check the Network tab to see information about what request is sent out and what response comes back. – Robin Zigmond Feb 18 '19 at 12:36
  • When I select a date, it is passed to flask as `request.form.get("Date")` which I access and can print. Also, wouldn't a success callback function require another return which I need as my render_template? – nx_prv Feb 18 '19 at 12:39
  • Yes, so that proves the data is passed to the backend as a POST request. As I said, the issue is that you are not *doing* anything with the response. I see that @AndrejsCainikovs has now answered to tell you the same - does this make sense now? – Robin Zigmond Feb 18 '19 at 12:47
  • Ahh so I was creating the render_template again and that is what 'resets' the variable. Thank you all. – nx_prv Feb 18 '19 at 12:50

1 Answers1

1

You are getting the content of rendered template with Appointments into a response of your POST request. If you want to use Appointments data on your page, you need to extend your POST request with a callback which will use that data for whatever you need.

So basically what happens:

  1. Page loads (GET request), template is rendered with an empty Appointments list
  2. Page fires POST ajax request, which returns rendered template with Appointments set
  3. You are not processing POST response, hence this data is just discarded.

Typical approach is to obtain only relevant data (for example, in JSON format) from POST response, not a full page:

from flask import Response

if request.method == "POST":
    Date = request.form.get("Date")
    print(Date)
    Appointments=["This should show up."]
    return Response(json.dumps(Appointments), mimetype='application/json')
else:
    return render_template("PatientDashboard.html", Appointments=[]) 
Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
  • Thank you, how should I go about extending my POST request with a callback? – nx_prv Feb 18 '19 at 12:47
  • There's plenty of resources on how to use jQuery ajax callbacks. Here's a good template for you https://stackoverflow.com/a/28175715/147407 – Andrejs Cainikovs Feb 18 '19 at 12:53
  • Hmm.. I have tried out your sample and I get a `TypeError: dumps() missing 1 required positional argument: 'obj'`. Is this due to the `dataType`? – nx_prv Feb 18 '19 at 12:56
  • Normally Flask prints a trace message when error occurs. I cannot say where error comes from by just having server response code. But yes, you need to set `dataType: "json"` in your `$.ajax` call to indicate that you are dealing with JSON data. – Andrejs Cainikovs Feb 18 '19 at 13:00
  • Here's another link for you: https://techtutorialsx.com/2017/01/07/flask-parsing-json-data/, dealing with json data in requests on server side. – Andrejs Cainikovs Feb 18 '19 at 13:06
  • 1
    should be `return Response(json.dumps(Appointments), mimetype='application/json')` I think – Robin Zigmond Feb 18 '19 at 13:06
  • @RobinZigmond: Thanks, fixed. – Andrejs Cainikovs Feb 18 '19 at 13:07
  • I also edited the comment, there is no `mimetype` keyword argument for `json.dumps`, this should be in the `Response` function – Robin Zigmond Feb 18 '19 at 13:08
  • I'm guessing I can't simply output this in my HTML file by using `{{ Appointments }}`? – nx_prv Feb 18 '19 at 13:16
  • No. If you want to see that data on your page, then you obtain `Appointments` data from your POST response, and make changes on your existing DOM elemens. Here's a good start for you: `var data = JSON.parse(response); $('#result').html(data.Appointments[0]);` – Andrejs Cainikovs Feb 18 '19 at 13:22