by Guest » 03 Jan 2025, 11:19
Also erstelle ich eine App mit Flask mit flask.sqlalchemy, flask-forms, flask-login. In dieser App habe ich verschiedene Modelle, und eines davon ist dieses:
Code: Select all
from app import db
from sqlalchemy.orm import Mapped, mapped_column
from datetime import datetime, timezone
class Blog_Post(db.Model):
__tablename__ = "blog_post"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(db.String(60), nullable=False)
body: Mapped[str] = mapped_column(nullable=False)
image : Mapped[str] = mapped_column(nullable=False)
author: Mapped[str] = mapped_column(nullable=False)
date_created: Mapped[datetime] = mapped_column(nullable=False, default=datetime.now(timezone.utc))
Wie Sie sehen können, speichere ich den Titel, den Text, den Autor und das Bild (nur den Pfad zum Bild), die in einem Ordner wie diesem gespeichert sind:
Code: Select all
@app.route("/create_post", methods=["POST", "GET"])
@login_required
def create_post():
form = CreatePostForm()
user_id_folder = 'user-' + current_user.get_id()
user_folder = os.path.join(
app.static_folder, 'images', user_id_folder, 'post'
).replace('\\', '/')
if form.validate_on_submit():
f = form.file.data
filename = secure_filename(f.filename)
if filename:
try:
#check that the 'images/post/' folder exists, else it creates it
if not os.path.exists(user_folder):
os.makedirs(os.path.join(
user_folder
))
#built-in flask-wtf function to save images
final_save = os.path.join(
user_folder, filename
).replace('\\', '/')
f.save(final_save)
#charging post to database, only storing path to the image in the database
post = Blog_Post(
title= form.title.data,
body=form.body.data,
image = filename,
author= current_user.username)
db.session.add(post)
db.session.commit()
return redirect('/')
except Exception as e:
app.log_exception(f'There was an error uploading the image: {e=}')
abort(400)
except Exception as e:
return f"There was an error with creating the post: {e=}"
return render_template("posts/create_post.html", form=form)
und das Datum. Ich speichere es als UTC und bis dahin habe ich kein Problem, ich würde es so einfach machen wie {{ post.date_created.strf(something)}} und es würde den Zweck erfüllen.
Dann habe ich auf der Hauptseite, wo es ein Raster mit Bild, Titel, Erstellungsdatum und Autor gibt, gedacht: „Hätten die Leute nicht unterschiedliche Zeitzonen?“. Also begann ich zu suchen, wie man UTC in lokale Zeitzonen umwandelt, und entschied mich dafür, einfach die lokale Zeitzone vom Browser anzufordern, sie an eine Ansicht zu übergeben und dann die Konvertierung durchzuführen.
Die Hauptseite, auf der alle erstellten Beiträge angezeigt werden Ich zeige Folgendes:
Code: Select all
{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% block title %} Home {% endblock%}
{% block body %}
{% for post in posts%}
{% if current_user.is_authenticated%}
[img]{{ url_for([/img]
{% else %}
[img]{{ url_for([/img]
{% endif %}
[url=#]{{post.title}}[/url]
[h4]Date: {{url_for('convert_timezone', utc=post.date_created)}}[/h4]
[h4]Author: {{post.author}}[/h4]
{% endfor %}
{% endblock %}
Ansicht, von wo aus ich die Zeitzone vom Browser anfordere (es funktioniert):
Code: Select all
@app.route('/save-timezone', methods=['POST'])
def save_timezone():
print(f"Request path: {request.path}")
data = request.json
user_timezone = data.get('timezone') # Example of timezone: "America/New_York"
print(f"Received timezone: {user_timezone}")
return user_timezone
und dann habe ich eine benutzerdefinierte Funktion, die es mithilfe von user_timezone konvertiert, mit der Funktion astimezone von datetime, aber ich weiß nicht, wie ich den von dieser Ansicht zurückgegebenen Wert in der anderen Funktion verwenden soll , ich habe Folgendes versucht:
Code: Select all
@app.route("/convert_timezone//", defaults={'user_timezone' : 'save_timezone()'})
aber das gibt mir nur:
Code: Select all
[h4]Date: /convert_timezone/2025-01-02%2013:58:31.110859/save_timezone()[/h4]
Der offensichtliche Grund ist, dass save_timezone() nicht aufgerufen wird, weil es in Anführungszeichen steht, aber wenn ich versuche, es aufzurufen, erhalte ich Folgendes:
Code: Select all
Traceback (most recent call last):
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\run.py", line 1, in
from app import db, app
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\__init__.py", line 25, in
from app import routes
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\routes.py", line 157, in
^^^^^^^^^^^^^^^
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\routes.py", line 150, in save_timezone
print(f"Request path: {request.path}")
^^^^^^^^^^^^
File "c:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\.venv\Lib\site-packages\werkzeug\local.py", line 318, in __get__
obj = instance._get_current_object()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\.venv\Lib\site-packages\werkzeug\local.py", line 519, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
Ich möchte also wissen, ob ich etwas falsch mache (was es ist?), ob es einfach zu komplex für eine einfache Blog-Vorlage ist oder ob ich es einfach ignorieren und auf UTC belassen sollte ?
Bearbeiten:
Da es also eine Person gab, die nach der vollständigen Ansicht und der js-Funktion gefragt hat:
Code: Select all
const user_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// sending request
fetch('/save-timezone', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ timezone: user_timezone })
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
Die vollständige Ansicht und die benutzerdefinierte Funktion:
Code: Select all
@app.route("/convert_timezone//", defaults={'user_timezone' : 'save_timezone()'})
def convert_timezone(utc, user_timezone):
return utc2local(utc, user_timezone)
Die benutzerdefinierte Funktion (utc2local):
Code: Select all
from zoneinfo import ZoneInfo
from datetime import datetime
def utc2local(utc_reference, local_timezone):
if isinstance(utc_reference, str):
utc_reference = datetime.fromisoformat(utc_reference)
local_time = utc_reference.astimezone(tz=ZoneInfo(local_timezone))
return local_time
Also erstelle ich eine App mit Flask mit flask.sqlalchemy, flask-forms, flask-login. In dieser App habe ich verschiedene Modelle, und eines davon ist dieses:
[code]from app import db
from sqlalchemy.orm import Mapped, mapped_column
from datetime import datetime, timezone
class Blog_Post(db.Model):
__tablename__ = "blog_post"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(db.String(60), nullable=False)
body: Mapped[str] = mapped_column(nullable=False)
image : Mapped[str] = mapped_column(nullable=False)
author: Mapped[str] = mapped_column(nullable=False)
date_created: Mapped[datetime] = mapped_column(nullable=False, default=datetime.now(timezone.utc))
[/code]
Wie Sie sehen können, speichere ich den Titel, den Text, den Autor und das Bild (nur den Pfad zum Bild), die in einem Ordner wie diesem gespeichert sind:
[code]@app.route("/create_post", methods=["POST", "GET"])
@login_required
def create_post():
form = CreatePostForm()
user_id_folder = 'user-' + current_user.get_id()
user_folder = os.path.join(
app.static_folder, 'images', user_id_folder, 'post'
).replace('\\', '/')
if form.validate_on_submit():
f = form.file.data
filename = secure_filename(f.filename)
if filename:
try:
#check that the 'images/post/' folder exists, else it creates it
if not os.path.exists(user_folder):
os.makedirs(os.path.join(
user_folder
))
#built-in flask-wtf function to save images
final_save = os.path.join(
user_folder, filename
).replace('\\', '/')
f.save(final_save)
#charging post to database, only storing path to the image in the database
post = Blog_Post(
title= form.title.data,
body=form.body.data,
image = filename,
author= current_user.username)
db.session.add(post)
db.session.commit()
return redirect('/')
except Exception as e:
app.log_exception(f'There was an error uploading the image: {e=}')
abort(400)
except Exception as e:
return f"There was an error with creating the post: {e=}"
return render_template("posts/create_post.html", form=form)
[/code]
und das Datum. Ich speichere es als UTC und bis dahin habe ich kein Problem, ich würde es so einfach machen wie {{ post.date_created.strf(something)}} und es würde den Zweck erfüllen.
Dann habe ich auf der Hauptseite, wo es ein Raster mit Bild, Titel, Erstellungsdatum und Autor gibt, gedacht: „Hätten die Leute nicht unterschiedliche Zeitzonen?“. Also begann ich zu suchen, wie man UTC in lokale Zeitzonen umwandelt, und entschied mich dafür, einfach die lokale Zeitzone vom Browser anzufordern, sie an eine Ansicht zu übergeben und dann die Konvertierung durchzuführen.
Die Hauptseite, auf der alle erstellten Beiträge angezeigt werden Ich zeige Folgendes:
[code]{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% block title %} Home {% endblock%}
{% block body %}
{% for post in posts%}
{% if current_user.is_authenticated%}
[img]{{ url_for([/img]
{% else %}
[img]{{ url_for([/img]
{% endif %}
[url=#]{{post.title}}[/url]
[h4]Date: {{url_for('convert_timezone', utc=post.date_created)}}[/h4]
[h4]Author: {{post.author}}[/h4]
{% endfor %}
{% endblock %}
[/code]
Ansicht, von wo aus ich die Zeitzone vom Browser anfordere (es funktioniert):
[code]@app.route('/save-timezone', methods=['POST'])
def save_timezone():
print(f"Request path: {request.path}")
data = request.json
user_timezone = data.get('timezone') # Example of timezone: "America/New_York"
print(f"Received timezone: {user_timezone}")
return user_timezone
[/code]
und dann habe ich eine benutzerdefinierte Funktion, die es mithilfe von user_timezone konvertiert, mit der Funktion astimezone von datetime, aber ich weiß nicht, wie ich den von dieser Ansicht zurückgegebenen Wert in der anderen Funktion verwenden soll , ich habe Folgendes versucht:
[code]@app.route("/convert_timezone//", defaults={'user_timezone' : 'save_timezone()'})
[/code]
aber das gibt mir nur:
[code][h4]Date: /convert_timezone/2025-01-02%2013:58:31.110859/save_timezone()[/h4]
[/code]
Der offensichtliche Grund ist, dass save_timezone() nicht aufgerufen wird, weil es in Anführungszeichen steht, aber wenn ich versuche, es aufzurufen, erhalte ich Folgendes:
[code]Traceback (most recent call last):
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\run.py", line 1, in
from app import db, app
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\__init__.py", line 25, in
from app import routes
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\routes.py", line 157, in
^^^^^^^^^^^^^^^
File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\routes.py", line 150, in save_timezone
print(f"Request path: {request.path}")
^^^^^^^^^^^^
File "c:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\.venv\Lib\site-packages\werkzeug\local.py", line 318, in __get__
obj = instance._get_current_object()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\.venv\Lib\site-packages\werkzeug\local.py", line 519, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
[/code]
Ich möchte also wissen, ob ich etwas falsch mache (was es ist?), ob es einfach zu komplex für eine einfache Blog-Vorlage ist oder ob ich es einfach ignorieren und auf UTC belassen sollte ?
Bearbeiten:
Da es also eine Person gab, die nach der vollständigen Ansicht und der js-Funktion gefragt hat:
[code]const user_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// sending request
fetch('/save-timezone', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ timezone: user_timezone })
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
[/code]
Die vollständige Ansicht und die benutzerdefinierte Funktion:
[code]@app.route("/convert_timezone//", defaults={'user_timezone' : 'save_timezone()'})
def convert_timezone(utc, user_timezone):
return utc2local(utc, user_timezone)
[/code]
Die benutzerdefinierte Funktion (utc2local):
[code]from zoneinfo import ZoneInfo
from datetime import datetime
def utc2local(utc_reference, local_timezone):
if isinstance(utc_reference, str):
utc_reference = datetime.fromisoformat(utc_reference)
local_time = utc_reference.astimezone(tz=ZoneInfo(local_timezone))
return local_time
[/code]