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.
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
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)
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:
form.addEventListener('submit', function(event) {
event.preventDefault(); // prevent page from refreshing
const formData = new FormData(form); // grab the data inside the form fields
fetch("https://stackoverflow.com/", { // assuming the backend is hosted on the same server
method: 'POST',
body: formData,
}).then(function(response) {
// do something with the response if needed.
// If you want the table to be built only after the backend handles the request and replies, call buildTable() here.
});
});