"form.populate_by возвращает" ОШИБКА: объект списка не имеет атрибута - PullRequest
1 голос
/ 30 марта 2019

Я создаю функцию представления для редактирования базы данных с помощью wtform. Я хочу заполнить форму информацией, хранящейся в базе данных, предоставленной другой формой. Моя проблема - запрос, предоставляющий подробности

Я прочитал инструкцию https://wtforms.readthedocs.io/en/stable/crash_course.html и следующий вопрос Python Flask-WTF - использовать тот же шаблон формы для операций добавления и редактирования но мой запрос, похоже, не предоставляет правильный формат данных

модель базы данных:

class Sensors(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    sensorID = db.Column(db.String, unique=True)
    name = db.Column(db.String(30), unique=True)

форма модели:

class AddSensorForm(FlaskForm):
    sensorID = StringField('sensorID', validators=[DataRequired()])
    sensorName = StringField('sensorName', validators=[DataRequired()])
    submit = SubmitField('Register')

функция просмотра:

@bp.route('/sensors/editsensor/<int:id>', methods=('GET', 'POST'))
@login_required
def editsensor(id):
    edit = [(s.sensorID, s.sensorName) for s in db.session.\
      query(Sensors).filter_by(id=id).all()]
    form = AddSensorForm(obj=edit)
    form.populate_obj(edit)
    if form.validate_on_submit():
        sensors = Sensors(sensorID=form.sensorID.data, sensorName=form.sensorNa$
        db.session.add(sensors)
        db.session.commit()

код оболочки для запроса:

from homeHeating import db
from homeHeating import create_app
app = create_app()
app.app_context().push()
def editsensor(id):
    edit = [(s.sensorID, s.sensorName) for s in db.session.query(Sensors).filter_by(id=id).all()]
    print(edit)

editsensor(1)
[('28-0000045680fde', 'Boiler input')]

Я ожидаю, что два поля формы будут заполнены информацией о датчике, называемом его «id» но я получаю эту ошибку

File "/home/pi/heating/homeHeating/sensors/sensors.py", line 60, in 
editsensor
form.populate_obj(edit)
File "/home/pi/heating/venv/lib/python3.7/site- 
packages/wtforms/form.py", line 96, in populate_obj
Open an interactive python shell in this 
framefield.populate_obj(obj, name)
File "/home/pi/heating/venv/lib/python3.7/site- 
packages/wtforms/fields/core.py", line 330, in populate_obj
setattr(obj, name, self.data)
AttributeError: 'list' object has no attribute 'sensorID'

Ошибка указывает, что оно хочет, чтобы 2 части для каждого поля "framefield.populate_obj (obj, name) mine" предоставляло только один столбец данных, но не имя столбца "sensorID" Если я хэширую # строку "edit = ...", то сообщений об ошибках нет, и форма возвращается, но поля пусты. Поэтому я хочу, чтобы форма возвращалась вместе с информацией в базе данных, чтобы я мог изменить имя или идентификатор датчика, а затем обновить базу данных.

Надеюсь, это понятно

С уважением

Paul.

ps Я следовал инструкции, поэтому оператор ERROR является только частью после "field.populate_by".

1 Ответ

1 голос
/ 30 марта 2019

Вы пытаетесь передать в форму список из 1 элемента.

Как правило, когда вы выбираете одну запись на основе первичного ключа вашей модели, используйте Query.get () вместо Query.filter (...). All () [0].

Кроме того, вам необходимо передать данные запроса в форму для проверки их при отправке, а также для предварительного заполнения полей, когда форма сообщает об ошибках.

Form.validate_on_submit будет возвращать True, только если ваш метод запроса POST и ваша форма проходит проверку; это шаг, когда ваша форма сообщает вам «пользователь предоставил синтаксически правильную информацию, теперь вы можете делать больше проверок, и я могу заполнить существующий объект данными, предоставленными мне».

Вам также необходимо обработать случаи, когда форма отображается пользователю впервые.

@bp.route('/sensors/editsensor/<int:id>', methods=('GET', 'POST'))
@login_required
def editsensor(id):
    obj = Sensors.query.get(id) or Sensors()
    form = AddSensorForm(request.form, obj=obj)

    if form.validate_on_submit():
        form.populate_obj(obj)
        db.session.add(obj)
        db.session.commit()

        # return response or redirect here
        return redirect(...)

    else:
        # either the form has errors, or the user is displaying it for
        # the first time (GET)

        return render_template('sensors.html', form=form, obj=obj)
...