I’m building a simple To-Do List app in Flask, and I’ve created a form that’s supposed to add a task within a user’s account.
Flask Form:
class AddTask(FlaskForm):
title = StringField('Title', validators = [DataRequired()])
description = StringField('Description')
project = SelectField('Project', choices = [], validators = [DataRequired()])
due_date_time = DateField('Due Date', format = '%Y-%m-%d')
priority = RadioField('Priority', choices = [(1, 'Priority 1'), (2, 'Priority 2'), (3, 'Priority 3'), (4, 'Priority 4')])
submit = SubmitField('Add Task')
attributes_to_clear = [title, description, project, due_date_time, priority]
HTML Code:
<div class = "new_task_form">
<form action = "/app/today" method = "POST">
{{ new_task_form.hidden_tag() }}
{{ new_task_form.csrf_token }}
{{ new_task_form.title.label }}
{{ new_task_form.title }}
{% if new_task_form.title.errors %}
<ul class="errors">
{% for error in new_task_form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ new_task_form.description.label }}
{{ new_task_form.description }}
{{ new_task_form.project.label }}
{{ new_task_form.project }}
{{ new_task_form.due_date_time.label }}
{{ new_task_form.due_date_time }}
{{ new_task_form.priority.label }}
{{ new_task_form.priority }}
{{ new_task_form.submit() }}
</form>
</div>
Route:
@app.route('/app/today', methods = ['POST', 'GET'])
@login_required
def today():
today = datetime.today().strftime('%a %b %d')
projects = [(project.id, project.title) for project in Project.query.filter(Project.user_id == current_user.id).all()]
new_task_form = AddTask()
new_task_form.project.choices = projects
logger.info(f'new_task_form.project.choices: {new_task_form.project.choices}')
if new_task_form.validate_on_submit():
logger.info(f'new_task_form.validate_on_submit() returned {new_task_form.validate_on_submit()}')
project_from_form = Project.query.filter(Project.id == new_task_form.project.data).first()
logger.error(f'project_from_form: {project_from_form}')
new_task = Task(
title = new_task_form.title.data,
description = new_task_form.description.data,
project = project_from_form,
due_date_time = new_task_form.due_date_time.data,
priority_level = new_task_form.priority.data,
user_id = current_user.id
)
db.session.add(new_task)
db.session.commit()
else:
logger.info(f'new_task_form.validate_on_submit(): Returned {new_task_form.validate_on_submit()}')
logger.info(f'new_task_form.errors: {new_task_form.errors}')
pending_tasks = Task.query.filter(Task.user_id == current_user.id, Task.completed_status == 0).all()
pending_tasks_length = len(pending_tasks)
logger.info(f'current_user: {current_user.id}')
logger.info(f'pending_tasks_length: {pending_tasks_length}')
logger.info(f'pending_tasks: {pending_tasks}')
return render_template('today.html',
day_and_date = today,
new_task_form = new_task_form,
user_projects = projects,
pending_tasks_length = pending_tasks_length,
pending_tasks = pending_tasks)
The issue I’m running into is that I don’t want the page to refresh after submitting. Right now it works in the sense that you can add a task and it’ll populate immediately on the page. However, the actual Flask Form will keep whatever you plugged in previously and a refresh will cause it to resubmit. I’ve looked around but couldn’t find a way to eliminate the text, I’ve tired using the default
values, building functions that would reset them to just an empty string, but nothing I’ve tried so far fixes this particular issue.
2
Answers
Here you are sending this html to the user even after submitting a successful entry to your database with the same form that has been completed
What you are trying to do will require some javascript since flask cannot do this on its own.
I suggest reading this answer: https://stackoverflow.com/a/62081993/22796342
They provide this code:
The idea is that after form validation if you redirect to the current page, the flask actually clears your form data and it won’t be submitted again when the user refreshes the page. After redirecting, the form will be completely empty.