skip to Main Content

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


  1. 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('/', {   // 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.
            });
        });
    
    Login or Signup to reply.
  2. @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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search