Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python A Social Network with Flask How to Win Friends Suggestions

Andy Hughes
Andy Hughes
8,113 Points

Can't find a video related to 'updating' records.

Ok so I am practising like crazy to extend Kenneth's social app in order to learn, understand and practice.

I am working on the CRUD principle and so far I've managed to figure out CR & D, but I can't find anywhere that shows how to do the Update part. If anyone can point me in the right direction or link a video I would be grateful.

So the social app is using Peewee and Sqlite and I've got the hang of creating forms, models and the functions. What I'm now trying to do is show a list of rows from the database and then have a button that essentially takes the ID of the row, populates the content of that row into a form that can then be used to update the row in the database.

I've managed to create the Form, View and Function and when I click on the 'update' button, it takes me to a new page which has the ID in the URL (all good!).

But it doesn't show me the form to update. Plus there are no error messages to help me figure it out.

I've included my code below just in case anyone can see anything obvious I'm missed.

Thanks :)

app.py

'''updates a standard'''
@app.route('/update_standard/<int:id>', methods=('GET', 'POST'))
@login_required
def update_standard(id):
    form = forms.UpdateForm()
    if form.validate_on_submit():
        models.Standards.update_standard(
            section=form.section.data,
            standard=form.standard.data
        )
        flash("Standard updated! Thanks!", "success")
        return redirect(url_for('standards'))
    return render_template('standards-list.html', form=form)


'''Creating the view for Standards table in database'''
@app.route('/standards')
def view_standards():
    standards = models.Standards.select()
    return render_template('standards-list.html', standards=standards)

models.py

class Standards(Model):
    section = CharField(unique=False)
    standard = CharField(unique=True)

    class Meta:
        database = DATABASE

    @classmethod
        def update_standard(cls, id, section, standard):
            try:
                with DATABASE.transaction():
                    cls.update(
                        id=id,
                        section=section,
                        standard=standard)
            except IntegrityError:
                raise ValueError("Standard does not exist for update")

forms.py

class UpdateForm(FlaskForm):
    section = TextAreaField('Set section title', validators=[DataRequired(), section_exists])
    standard = TextAreaField('Enter the standard to be added', validators=[DataRequired(), standard_exists])

standards-list.html

{% extends "layout.html" %} {% block content %}
<div class="flex-table">
    <div class="table-body">
        {% for standard in standards %}
        <div class="table-block">
            <div class="table-row">
                <div class="table-title shade-1">ID</div>
                <div class="table-content shade-1">{{ standard.id }}</div>
            </div>
            <div class="table-row">
                <div class="table-title shade-2">Section</div>
                <div class="table-content shade-2">{{ standard.section }}</div>
            </div>
            <div class="table-row">
                <div class="table-title shade-3">Standard</div>
                <div class="table-content shade-3">{{ standard.standard }}</div>
            </div>
            <div class="table-row">
                <div class="edit"><a href="/update_standard/{{ standard.id }}">Edit</a></div>
                <div class="delete"><a href="/standards/{{ standard.id }}">Delete</a></div>
            </div>
        </div>
        {% endfor %}
    </div>
</div>
{% endblock %}

update_standard.html

{% extends 'layout.html' %}{% from 'macros.html' import render_field %} {% block content %}
<form method="POST" action="">
    {{ form.hidden_tag() }} {% for field in form %} {{ render_field(field) }} {% endfor %}
    <button type="submit" id="submit">Update Standard</button>
</form>
{% endblock %}
Andy Hughes
Andy Hughes
8,113 Points

So I've managed to make a little progress. In the list of standards, when I click the 'edit/update' link it redirects to my 'update_standard/4' page where 4 is the id fed from the function. My form shows up but when I enter anything into the form and press the update button, it goes back to my list of standards, but the database has not changed.

I'm thinking that I've not coded either the function or the update class correctly so it almost doesn't know what to do with the information I submit to the form.

Also, I'd like the rendered form to contain the old information that is currently in the database. Is there a way to change the form to achieve this? I've tried to use {{ Standards.name }} in the TextField but I get an error saying 'non hashable type'.

Updated code is below:

app.py

'''updates a standard'''
@app.route('/update_standard/<int:id>', methods=('GET', 'POST'))
@login_required
def update_standard(id):
    form = forms.UpdateForm()
    if form.validate_on_submit():
        models.Standards.update_standard(
            id=form.section.data,
            section=form.section.data,
            standard=form.standard.data
        )
        flash("Standard updated! Thanks!", "success")
        return redirect(url_for('view_standards'))
    return render_template('update-standard.html', form=form, id=id)

models.py

    @classmethod
    def update_standard(cls, id, section, standard):
        try:
            with DATABASE.transaction():
                cls.update(
                    id=id,
                    section=section,
                    standard=standard)
        except IntegrityError:
            raise ValueError("Standard does not exist for update")

forms.py

class UpdateForm(FlaskForm):
    section = TextAreaField('Enter new section', validators=[DataRequired(), section_exists])
    standard = TextAreaField('Enter new standard', validators=[DataRequired(), standard_exists])

1 Answer

Mel Rumsey
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree seal-36
Mel Rumsey
Treehouse Staff

Hey Andy Hughes ! Glad you were able to get the updating figured out. To fill in a TextField, you can set the html attribute value equal to {{ Standards.name }}.

One of our incredible teachers Megan redid this course with Flask and SQLalchemy and she shows the whole CRUD process and how to add the data into the forms. I highly recommend it when you are finished with Kenneth's course.

Happy coding!

Andy Hughes
Andy Hughes
8,113 Points

Hi Mel,

Thank you for the reply. I know about the value attribute from my html days. Sometimes, I guess you can't see what's staring you straight in the face lol. Thanks again.

I have watched the Flask and SQLalchemy videos, but I'm not versed enough to know how to convert the SQLite database that Kenneth coded in and using SQLalchemy. Is it as simple as changing the initial database type and the rest should work? I suspect not but I really don't know. :)