Search code examples
htmlflaskflask-sqlalchemyflask-wtforms

Clear Flask Form after submit without refreshing page


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.


Solution

  • @app.route('/app/today', methods = ['POST', 'GET'])
    @login_required
    def today():
        #do some stuff
        if new_task_form.validate_on_submit():
            #do stuff and add to database
            db.session.add(new_task)
            db.session.commit()
            return  redirect(url_for('today'))
        else:
            #do stuff if the form is not validated properly
            return  redirect(url_for('today'))
        #contuinou
      
        return render_template('today.html', #pass some stuff to the page)
    

    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.