-3

so suppose that I want to keep track of weather the user has dark mode enabled or not. if it is user's first time, the theme is set to be system preferences.

in my python code, I am simply keeping track of the state. it is set to None by default, since we don't know users settings, yet!

from flask import Flask, render_template

app = Flask(__name__)

state_dark = None

@app.route('/')
def home():
    return render_html('home.html', state_dark = state_dark)

then I have some html and some javascript. the javascript first sets the theme by system preferences. then it has a button to toggle it on and off.

let darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;

const toggleLightDarkMode = () => {
    darkMode = !darkMode;
    html.setAttribute('data-theme', darkMode ? 'dark' : 'light');
}

as you can see the state_dark variable in python and the darkMode variable in javascript are not linked together at all. I need them to be linked, since some parts of my code work with python and some with javascript. I'd wish if I could do it like this.

let darkMode;
{% if state_dark == None %}
    darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
{% else %}
    darkMode = {{ state_dark }}
{% endif %}

const toggleLightDarkMode = () => {
    darkMode = !darkMode;
    {{ state_dark }} = darkMode;

    html.setAttribute('data-theme', darkMode ? 'dark' : 'light');
}

I've seen numerous other stack overflow posts about this, but none of them sadly worked. so I would like an answer actually explaining me the solutions to this example.

I see my question has been reported as duplicate, even though I mentioned some stuff above. I understand the gesture, but What is the difference between client-side and server-side programming? doesn't answer my question. I wanna know how to do it in python, not php.

  • You can't do that. You can inject a python value into JS easily enough, but you can't store a Javascript value in a Python variable that way. Honestly why does the *server* need to know or care about light vs dark mode? Just handle it on the client. – Jared Smith Mar 02 '23 at 19:24
  • @JaredSmith dark/light was just an example, so I could understand linking the two languages together. – KianFakheriAghdam Mar 03 '23 at 04:39
  • In Python the JS is just an inert string of text, you can inject a Python value into it with jinja or even str.format. But on the JS side there is no Python: it may be running on a server on the other side of the planet. You can send a request to the server with fetch, but the context of the original request is gone: HTTP requests are stateless. If you want to persist data between requests you'll need to store it in a database and then query the db on each request. – Jared Smith Mar 03 '23 at 11:56

1 Answers1

1

You can use jinja templates and embedded JS inside the HTML Python

@app.route('/')
def home():
    return render_html('home.html', state_dark=state_dark)

HTML

<script>
  let state_dark = "{{state_dark}}"
  let darkMode;
  if (state_dark == "None") {
      darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  } else {darkMode = state_dark}
</script>

To pass data back to Flask, you have to send data using fetch requests.

JS

async function sendData(data) {
  await fetch("/send?data="+data)
}

Flask

from flask import request

@app.route('/send')
def recieve():
  global state_dark
  state_dark = request.args.get('data')
walker
  • 444
  • 2
  • 12
  • You want to set *global state* from an http request? – Jared Smith Mar 03 '23 at 01:01
  • Yea, the only way to access it is to make it global...? I don't see how else he is supposed to get it. – walker Mar 03 '23 at 02:46
  • You can't do that: HTTP requests are independent and supposed to be stateless, and Flask assumes you know that. Generally in prod you'll be using a WSGI server like gunicorn or apache and the update fetch call might not even hit the same *process/thread* as the previous request, not to mention even if it did you'd be changing the state for *every user making requests*. https://stackoverflow.com/questions/32815451/are-global-variables-thread-safe-in-flask-how-do-i-share-data-between-requests – Jared Smith Mar 03 '23 at 11:52
  • Well obviously his solution right now won't handle multiple users since every time a user sets a request, it changes the global theme state so that's not even the issue. What I'm saying is if he's only using the application for himself, he would need to globalize the variable to access it... – walker Mar 03 '23 at 18:05
  • ...again, not if OP is using pretty much **any** of the popular WSGI servers (it would be entirely possible to change the theme and then on a subsequent request see the old variant), and your answer contains *no warnings* about the issues of using a global variable with HTTP requests when there are tons of issues. The goal here is not to give the OP more rope with which to hang him/herself. – Jared Smith Mar 03 '23 at 18:21
  • I don't see why you're acting as if OP is going to publish and deploy this project. If OP obviously isn't going to do this, there isn't really a good reason to find a more efficient solution (not that you even gave one). The solution would work for their scenario and solve the problem which they brought up and that's it. I'm not claiming that it would work for actual deployment but that's not something that OP requested so I didn't offer it. – walker Mar 03 '23 at 19:36
  • The mission of Stack Overflow is to *build a collection of high-quality Q&As for programming questions* what about the next 50 clueless noobs who google this and stumble across your answer? Your answer not only doesn't fix the problem but does nothing to correct the OP and subsequent searchers (and your own?) misconceptions about how web servers work. I'm done. I've already downvoted, and I'm not removing it until you clean this up. – Jared Smith Mar 03 '23 at 19:44
  • Side note: I agree that globalizing variables in HTTP requests is probably bad practice but it does offer a solution that works. – walker Mar 03 '23 at 19:50