python - How can i make this default value work, since the value is a view with data being requested from the user? - Stack Over

admin2025-05-01  1

So im making an app with flask with flask.sqlalchemy, flask-forms, flask-login, within that app i have varius models, and one of those is this:

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))

as u can see, im storing the tittle, body, author, image (only the path to the img, that are stored in a folder like this:

@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/<user>' 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.sessionmit()
                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)

and the date. Im storing it as UTC and till then, i have no problem i would do it as simple as {{ post.date_created.strf(something)}} and it would do the trick.

Then in the main page, where have a grid showing the img,title, date_created and author i was thinking "Wouldnt people have diferent timezones?". So i started looking how to convert UTC to Localtimezones and i choose to just request the localtimezone from the browser, pass it to one view and then make the conversion. The main page where all the posts created are going to be displayed im showing the following:

{% extends 'base.html' %}

{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='index.css')}}">
{% endblock %}

{% block title %} Home {% endblock%}

{% block body %}
    <div class="grid-container">
        {% for post in posts%}
            <div class="post-container">
                {% if current_user.is_authenticated%}
                <img src="{{ url_for('show_images', user=current_user.get_id(), filename=post.image)}}" alt="" class="scale">
                {% else %}
                <img src="{{ url_for('show_images', user=1, filename=post.image)}}" alt="" class="scale">
                {% endif %}
                <a href="#"><h3>{{post.title}}</h3></a>
                <h4>Date: {{url_for('convert_timezone', utc=post.date_created)}}</h4>
                <h4>Author: {{post.author}}</h4> 
            </div>
        {% endfor %}

        
    </div>
{% endblock %}

View from where i request the timezone from the browser (its working):

@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

and then i have a custom function that will convert it using the user_timezone, with the function astimezone from datetime, but i dont know how to use the value returned by this view in the other function, i tried the following:

@app.route("/convert_timezone/<utc>/<user_timezone>", defaults={'user_timezone' : 'save_timezone()'})

but that only gives me:

<h4>Date: /convert_timezone/2025-01-02%2013:58:31.110859/save_timezone()</h4>

The obvius reason is that the save_timezone() isnt being called because is in quotation mark, but when i try to call it i get:

Traceback (most recent call last):
  File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\run.py", line 1, in <module>
    from app import db, app
  File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\__init__.py", line 25, in <module>
    from app import routes
  File "C:\Programing utilities\Ps\Flask\Flask_tutorial-uniwebsidad\Web-Blog\app\routes.py", line 157, in <module>
                                                                                      ^^^^^^^^^^^^^^^
  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.

So, i want to know if am i doing something wrong (what it is?), is just too complex for a simple blog template or i should just ignore it and leave it as UTC?

Edit: So since there was one person asking for the complete view and the js function:

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));

The complete view and the custom function:

@app.route("/convert_timezone/<utc>/<user_timezone>", defaults={'user_timezone' : 'save_timezone()'})
def convert_timezone(utc, user_timezone):
    return utc2local(utc, user_timezone)

The custom function (utc2local):

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
转载请注明原文地址:http://www.anycun.com/QandA/1746103192a91709.html