-2

I'm trying to use FullCalendar with Flask. I'd like for when a date is clicked on the calendar page, for it to redirect to a 'day' page based on that date. Right now I just want it to redirect to a day page that says that date at the top, and I'll add more formatting once I get that working.

I'm using url_for to redirect to the day page, but it doesn't seem to be passing the date to the url. It just goes to a '404 url not found' page, and the url doesn't include the date, it's just "localhost:5000/day/" when I was expecting it to be "localhost:5000/day/2023-03-09' or whatever date was selected.

I tried logging the date to the console when the date is clicked and that works. I've also tried manually going to localhost:5000/day/2023-03-09 and that takes me to the page I'm expecting as well. I can see the issue is that the date is not being passed, but I'm not sure why that's the case. Any help is greatly appreciated!

Here is the cal.html page:

<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8' />
    <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.4/index.global.js'></script>
    <script>

      document.addEventListener('DOMContentLoaded', function() {
        var calendarEl = document.getElementById('calendar');
        var calendar = new FullCalendar.Calendar(calendarEl, {
          initialView: 'dayGridMonth',
          dateClick: function(info) {
            date = info.dateStr
            window.location.href = {{ url_for('cal.day', date=date) }}
            },

        });
        calendar.render();
      });

    </script>
  </head>
  <body>
    <div id='calendar'></div>
  </body>
</html>

and here is my routes.py:

from flask import render_template, Blueprint


cal = Blueprint('cal', __name__, template_folder='templates', static_folder='static',
                 static_url_path='/cal/static')


@cal.route('/', methods=['GET'])
def calendar():
    return render_template('cal.html')


@cal.route('/day/<date>', methods=['GET', 'POST'])
def day(date):
    date=date
    return render_template('day.html', date=date)

day.html is:

<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8' />
  </head>
  <body>
    <h1>{{date}}</h1>
  </body>
</html>
davidism
  • 121,510
  • 29
  • 395
  • 339
AprilMay
  • 1
  • 1
  • Can you try `` in your route? – Abdullah Akçam Mar 10 '23 at 07:42
  • Anything inside the `{{ ... }}` is python/flask code, right? So how do you expect it to read a JS variable which a) is from a different language and runtime environment, and b) isn't set until after the python code has already executed? For background have a read of [What is the difference between client-side and server-side programming?](https://stackoverflow.com/questions/13840429/what-is-the-difference-between-client-side-and-server-side-programming) (although it talks about PHP a lot, the principle is identical no matter what the server-side language is) – ADyson Mar 10 '23 at 11:58
  • @AbdullahAkçam it's generating the wrong URL to go to, so it's not even reaching the route. Read the question again. – ADyson Mar 10 '23 at 12:08
  • I tried that, it does the same thing. I found a workaround using window.location.href = '/day/' + info.dateStr – AprilMay Mar 11 '23 at 02:23
  • Tried what? My answer below you mean? It should work i think, assuming the python does what I think it should – ADyson Mar 11 '23 at 08:51

1 Answers1

0

You can't expect a flask/python block to be able to read a JS variable (date in this case) which a) is from a different language and runtime environment, and b) isn't set until after the python code has already executed.

Clearly it's useful to have flask generate the URL route correctly (instead of hard-coding it into the JS), but you can't know the final date string to use until after the python code has run.

A workaround for this is to put a placeholder value into the URL string that python generates, and then use JavaScript to replace that placeholder text with the real date string when the dateClick callback runs.

I'm not a regular python or flask user, so I hope I've got that bit of the syntax right, but even if not, hopefully you can see the basic idea:

dateClick: function(info) {
  date = info.dateStr;
  url = {{ url_for('cal.day', date='###') }}
  url = url.replace("###", date);
  window.location.href = url;
},
ADyson
  • 57,178
  • 14
  • 51
  • 63