Flask-SQLAlchemy не будет обновлять или удалять строку

Я хочу либо обновить строку в базе данных, если она существует, либо создать ее, если ее нет.

У меня есть класс, который сначала устанавливает переменную экземпляра user:

self.user = models.User.query.filter_by(entity=self.entityUrl).first()
# can be None if not found

Затем, позже в другом методе класса я делаю это:

if self.user is not None:
    self.user.foo = bar  # etc. Change the attributes of self.user
else:
    self.user = models.User(bar, ... )  # create a new model
    db.session.add(self.user)
db.session.commit()

Проблема в том, что соответствующая строка в базе данных не обновляется. Я также пробовал этот подход:

if self.user is not None:
    self.user.foo = bar
else:
    self.user = models.User(bar, ... )
db.session.add(self.user)  # add it to the session either way
db.session.commit()

Здесь вызов db.session.add() завершается с ошибкой sqlalchemy.exc.InvalidRequestError: Object '<User at 0x7f4918172890>' is already attached to session '1' (this is '2')

И первое, что я попробовал, это удалить существующую модель во всех случаях, а затем создать новую, т.е.:

if self.user is not None:
    db.session.delete(self.user)
self.user = models.User(bar, ... )
db.session.add(self.user)
db.session.commit()

В этом случае вызов db.session.delete() завершается ошибкой с тем же сообщением already attached to session '1', что и выше.

Почему объект привязан к другому сеансу, а не к тому же? Как мне это сделать правильно?


person Scott F    schedule 01.01.2013    source источник


Ответы (2)


Убедитесь, что атрибут foo в вашем классе существует. Далее, возможно, что-то не так в том, как вы его используете. Потому что я вижу, что вы используете "self.user....". Сначала попробуйте самое простое. Затем шаг за шагом.

Следующий код неверен:

if self.user is not None:
    self.user.foo = bar
else:
    self.user = models.User(bar, ... )
db.session.add(self.user)  # add it to the session either way
db.session.commit()

НЕТ необходимости db.session.add, если вы хотите обновить запись.

person bass chuck    schedule 05.12.2017

Чтобы обновить существующую запись с помощью Flask-SQLAlchemy, вам не нужно заново создавать весь объект User и добавлять его в сеанс. Вы просто обновляете конкретное поле (например, foo) и все. Затем вы можете выполнить фиксацию БД.

Вы можете выполнить точное требование, как показано ниже:

Шаг 1: запросите существующий пользовательский объект

user = models.User.query.filter_by(entity=self.entityUrl).first()

Шаг 2:

if user is not None:
     user.foo = bar
else:
    user = User(...)
    db.session.add(user) 

Шаг 3: зафиксируйте сеанс БД.

db.session.commit()
person codegeek    schedule 02.01.2013
comment
Это именно то, что делает мой код, за исключением того, что шаг 1 находится в методе, отличном от шагов 2-3. И БД не обновляется. Я посмотрю, смогу ли я уменьшить его до минимального примера. - person Scott F; 03.01.2013
comment
Хорошо, я думал, вы сказали # добавить его в сеанс в любом случае. Это может быть проблемой. Вы хотите добавить его в сеанс только в том случае, если это новый пользователь. На моем шаге 2 я только добавляю сеанс в блок else. Вы делаете то же самое? - person codegeek; 04.01.2013
comment
Как уже упоминалось, я пробовал оба способа. Если я добавлю его в сеанс при его изменении, я получаю сообщение об ошибке (что согласуется с тем, что вы говорите). Если я этого не сделаю, он не обновится. - person Scott F; 05.01.2013
comment
Шаг 1 отличается от шагов 2-3 методом. Возможно, пользовательский объект неправильно передается на следующие шаги. Вы можете проверить метод. Может быть почтовый индекс для этого здесь? - person codegeek; 30.01.2013