Home > Software design >  Unidentified form flask Jinja template attribute model
Unidentified form flask Jinja template attribute model

Time:08-24

I'm trying to create an edit form in flask, to compliment my working add and delete form - but I'm getting an error about items not being defined.

The template I have:

% extends "main/_base.html" %}
{% block title %}Edit Item{% endblock %}
{% from "main/_formshelper.html" import render_field %}

{% block content %}

<form action="{{ url_for('main.edit_item', items_id=item.Items.id) }}" method="post" name="edititemsform">
    {{ form.csrf_token }}
    <div >
      {{ form.name.label }}
      {{ render_field(form.name, , value=item.name) }}
    </div>
    <div >
      {{ form.notes.label }}
      {{ render_field(form.notes, , value=item.notes) }}
    </div>
    <input type="submit" value="Edit Item" >
</form>

{% endblock %}

The view that drives it:

@main_blueprint.route("/edit_item/<int:items_id>", methods=["GET", "POST"])
def edit_item(items_id):
    form = EditItemsForm(request.form)
    item_with_user = db.session.query(Items).filter(Items.id == items_id).first()
    if item_with_user is not None:
            if request.method == 'POST':
                if form.validate_on_submit():
                    try:
                        item = Items.query.get(items_id)
                        item.name = form.name.data
                        item.notes = form.notes.data
                        db.session.commit()
                        flash('Item edited')
                        return redirect(url_for('main.all_items'))
                    except:
                        db.session.rollback()
                        flash('Item edit error')
            return render_template('main/edit_item.html', item=item_with_user, form=form)
    else:
        flash('Item does not exist')
    return redirect(url_for('main.all_items'))

The error I get is :

 jinja2.exceptions.UndefinedError: 'app.main.models.Items object' has no attribute 'Items'

This is my model which I think is the root of the issue, is it that is looking for Items inside my model Items?

from app import db

class Items(db.Model):
    __tablename__ = 'items'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    notes = db.Column(db.String, nullable=True)

    def __init__(self, name, notes):
        self.name = name
        self.notes = notes

    def __repr__(self):
        return '<id {}>'.format(self.id)

CodePudding user response:

When creating the URL for the form's action parameter, you are referencing an incorrect attribute. You've already passed an Items object to the template and now you just need to request the id attribute and pass it to url_for.

<form 
  action="{{ url_for('main.edit_item', items_id=item.id) }}" 
  method="post" 
  name="edititemsform"
>
    <!-- ... -->
</form>

In order not to manually assign a value to every input field within the template, I recommend that you simply assign the object to be edited to the form. The validate_on_submit function then checks whether the request is of the POST type and whether the input is valid. Then you can use populate_obj to update all existing attributes. The database entry is then saved by commit.

@main_blueprint.route("/edit_item/<int:items_id>", methods=["GET", "POST"])
def edit_item(items_id):
    item = Items.query.get_or_404(items_id)
    form = EditItemsForm(request.form, obj=item)
    if form.validate_on_submit(): 
        form.populate_obj(item)
        try:
            db.session.commit()
            flash('Item edited')
            return redirect(url_for('main.all_items'))
        except:
            db.session.rollback()
            flash('Item edit error')
    return render_template('main/edit_item.html', **locals())
  • Related