Расширение для поддержки SQLAlchemy в Flask
Теперь, когда вы объявили модели, пришло время запрашивать данные из базы данных. Мы будем использовать определения моделей из главы «Быстрый старт».
Прежде чем мы сможем что-то запросить, нам нужно будет вставить некоторые данные. Все ваши модели должны иметь конструктор, поэтому обязательно добавьте его, если вы забыли. Конструкторы используются только вами, а не SQLAlchemy, так что вы сами можете их определять.
Вставка данных в базу данных состоит из трех этапов:
Session здесь это не Flask session, а session Flask-SQLAlchemy. По сути, это улучшенная версия транзакции базы данных. Вот как это работает:
from yourapp import User
me = User('admin', 'admin@example.com')
db.session.add(me)
db.session.commit()
Хорошо, это было не сложно. Что происходит и в какой момент? Прежде чем добавить объект в session, SQLAlchemy в основном не планирует добавлять его в транзакцию. Это хорошо, потому что вы все еще можете отказаться от изменений. Например, подумайте о создании поста на странице, но вы хотите передать пост только шаблону для предварительного просмотра, а не сохранять его в базе данных.
Вызов функции session.add()
добавляет объект. Он выдаст инструкцию INSERT для базы данных, но, поскольку транзакция
все еще не зафиксирована, вы не получите идентификатор немедленно. Если вы сделаете коммит, у вашего пользователя
будет идентификатор:
me.id
# 1
Удаление записей очень похоже, вместо session.add()
используйте session.delete()
:
db.session.delete(me)
db.session.commit()
Так как же нам вернуть данные из нашей базы данных? Для этого Flask-SQLAlchemy предоставляет атрибут query для вашего
класса Model. При обращении к нему вы получите новый объект query по всем записям. Затем вы можете использовать такие
методы, как query.filter()
, чтобы отфильтровать записи, прежде чем запускать select с all()
или first()
. Если вы
хотите перейти по первичному ключу, вы также можете использовать get()
.
Следующие запросы предполагают следующие записи в базе данных:
+----+----------+-------------------+
| id | username | email |
+----+----------+-------------------+
| 1 | admin | admin@example.com |
| 2 | peter | peter@example.org |
| 3 | guest | guest@example.com |
+----+----------+-------------------+
Получить пользователя по имени:
peter = User.query.filter_by(username='peter').first()
peter.id
# 2
peter.email
# u'peter@example.org'
То же, что и выше, но для несуществующего имени пользователя выдается None:
missing = User.query.filter_by(username='missing').first()
missing is None
# True
Выбор группы пользователей по более сложному выражению:
User.query.filter(User.email.endswith('@example.com')).all()
# [<User u'admin'>, <User u'guest'>]
Сортировка пользователей пользователей:
User.query.order_by(User.username).all()
# [<User u'admin'>, <User u'guest'>, <User u'peter'>]
Ограничение количества записей:
User.query.limit(1).all()
# [<User u'admin'>]
Получение пользователя по первичному ключу:
User.query.get(1)
# <User u'admin'>
Если вы пишете view функцию Flask, часто очень удобно возвращать ошибку 404 для несуществующих или ненайденных
записей. Поскольку это очень распространенная идиома, Flask-SQLAlchemy предоставляет помощника для этой конкретной
цели. Вместо get()
можно использовать get_or_404()
и вместо first()
аналог first_or_404()
. Это выдаст 404
ошибки вместо возврата None
:
@app.route('/user/<username>')
def show_user(username):
user = User.query.filter_by(username=username).first_or_404()
return render_template('show_user.html', user=user)