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())