Рубрики
Без рубрики

Интеграция MongoDB с Flask с помощью Flask-PyMongo

В этом уроке мы рассмотрим все, что вам нужно знать, чтобы интегрировать MongoDB с Flask и Python, создав функциональное приложение CRUD.

Вступление

Создание веб-приложения почти всегда означает работу с данными из базы данных. Существуют различные базы данных на выбор, в зависимости от ваших предпочтений.

В этой статье мы рассмотрим, как интегрировать одну из самых популярных баз данных NoSQLMongoDB – с микро-фреймворком Flask .

Существует несколько расширений Flask для интеграции MongoDB , здесь мы будем использовать расширение Flask-PyMongo .

Мы также будем работать над простым API Todo-List для изучения возможностей CRUD MongoDB.

Настройка и настройка

Чтобы следовать этому учебнику, вам понадобится доступ к экземпляру MongoDB, вы можете получить его из MongoDB Atlas или использовать локальный экземпляр. Мы будем использовать локальный экземпляр на нашей собственной персональной машине.

Чтобы установить локальный экземпляр MongoDB, зайдите на их официальный сайт документации для получения инструкций по его загрузке и установке.

Вам также нужно будет установить Flash , и если вы этого не сделаете, вы можете сделать это с помощью следующей команды:

$ pip install flask

Далее нам нужно настроить Flask-PyMongo , который представляет собой обертку вокруг пакета PyMongo python.

PyMongo-это низкоуровневая оболочка вокруг MongoDB, она использует команды, аналогичные командам MongoDB CLI для:

  1. Создание данных
  2. Доступ к данным
  3. Изменение данных

Он не использует никакой предопределенной схемы, поэтому может в полной мере использовать бесшемную природу MongoDB.

Чтобы начать использовать Flask-PyMongo, нам нужно установить его с помощью следующей команды.

$ pip install Flask-PyMongo

Теперь, когда все готово, давайте начнем интегрировать MongoDB в наше приложение Flask.

Подключение к экземпляру базы данных MongoDB с помощью Flask

Прежде чем мы действительно выполним какую-либо работу, мы хотим подключить наш экземпляр MongoDB к приложению Flask. Мы начнем с импорта Flask и Flask-PyMongo в наше приложение:

from flask_pymongo import PyMongo
import flask

Далее мы создадим объект приложения Flask:

app = flask.Flask(__name__)

Который мы затем будем использовать для инициализации нашего клиента MongoDB. Конструктор PyMongo (импортированный из flask_pymongo ) принимает наш объект приложения Flask и строку URI базы данных.

Это связывает наше приложение с экземпляром MongoDB:

mongodb_client = PyMongo(app, uri="mongodb://localhost:27017/todo_db")
db = mongodb_client.db

Строка URI также может быть назначена ключу MONGO_URI in app.config

app.config["MONGO_URI"] = "mongodb://localhost:27017/todo_db"
mongodb_client = PyMongo(app)
db = mongodb_client.db

Как только приложение имеет соединение с экземпляром, мы можем начать реализацию функциональности CRUD приложения.

Создание документов – Добавление новых элементов в базу данных

MongoDB работает с коллекциями, которые аналогичны обычной таблице SQL. Поскольку мы создаем приложение TODO list, у нас будет коллекция todos . Для ссылки на него мы используем объект db . Каждая сущность-это документ , а коллекция-это действительно коллекция документов.

Чтобы вставить новую запись в нашу коллекцию todos , мы используем метод db.collection.insert_one () . MongoDB естественно работает с Python, учитывая его синтаксис для вставки, запроса и удаления.

При вставке документа в коллекцию MongoDB вы должны указать словарь с s и s. Чтобы вставить документ в коллекцию MongoDB, используя Python в качестве посредника, вы передадите словари, встроенные в Python.

Таким образом, чтобы вставить новую сущность, мы сделаем что-то вроде:

@app.route("/add_one")
def add_one():
    db.todos.insert_one({'title': "todo title", 'body': "todo body"})
    return flask.jsonify(message="success")

Мы также можем добавить несколько записей одновременно, используя метод db.collection.insert_many () . Метод insert_many() берет список словарей и добавляет их в коллекцию:

@app.route("/add_many")
def add_many():
    db.todos.insert_many([
        {'_id': 1, 'title': "todo title one ", 'body': "todo body one "},
        {'_id': 2, 'title': "todo title two", 'body': "todo body two"},
        {'_id': 3, 'title': "todo title three", 'body': "todo body three"},
        {'_id': 4, 'title': "todo title four", 'body': "todo body four"},
        {'_id': 5, 'title': "todo title five", 'body': "todo body five"},
        {'_id': 1, 'title': "todo title six", 'body': "todo body six"},
        ])
    return flask.jsonify(message="success")

Если мы попытаемся добавить дублирующую запись, будет выброшен BulkWriteError , что означает, что будут вставлены только записи до указанного дубликата, а все, что после дубликата, будет потеряно, поэтому имейте это в виду при попытке вставить много документов.

Если мы хотим вставить в наш список только действительные и уникальные записи, нам придется установить параметр ordered метода insert_many() в значение false , а затем поймать исключение BulkWriteError :

from pymongo.errors import BulkWriteError

@app.route("/add_many")
def add_many():
    try:
        todo_many = db.todos.insert_many([
            {'_id': 1, 'title': "todo title one ", 'body': "todo body one "},
            {'_id': 8, 'title': "todo title two", 'body': "todo body two"},
            {'_id': 2, 'title': "todo title three", 'body': "todo body three"},
            {'_id': 9, 'title': "todo title four", 'body': "todo body four"},
            {'_id': 10, 'title': "todo title five", 'body': "todo body five"},
            {'_id': 5, 'title': "todo title six", 'body': "todo body six"},
        ], ordered=False)
    except BulkWriteError as e:
        return flask.jsonify(message="duplicates encountered and ignored",
                             details=e.details,
                             inserted=e.details['nInserted'],
                             duplicates=[x['op'] for x in e.details['writeErrors']])

    return flask.jsonify(message="success", insertedIds=todo_many.inserted_ids)

Этот подход позволит вставить все действительные документы в коллекцию MongoDB. Кроме того, он будет регистрировать сведения о неудачных добавлениях и распечатывать их обратно пользователю в виде сообщения JSON.

Мы сделали это с помощью метода Flasks jsonify () , который принимает сообщение, которое мы хотели бы вернуть, а также дополнительные параметры, позволяющие настроить его для целей ведения журнала.

Наконец, мы возвращаем успешные вставки, во многом таким же образом.

Чтение Документов – Извлечение Данных Из Базы Данных

Flask-PyMongo предоставляет несколько методов (расширенных от PyMongo) и некоторые вспомогательные методы для извлечения данных из базы данных.

Чтобы получить все документы из коллекции todos , мы используем метод db.collection.find () .

Этот метод вернет список всех todos в нашей базе данных. Подобно find() , метод find_one() возвращает один документ с учетом его идентификатора.

Давайте начнем с find() :

@app.route("/")
def home():
    todos = db.todos.find()
    return flask.jsonify([todo for todo in todos])

Метод find() также может принимать необязательный параметр фильтра. Этот параметр фильтра представлен словарем, который определяет свойства, которые мы ищем. Если вы раньше работали с MongoDB, то, вероятно, знакомы с тем, как выглядят их запросы и компараторы.

Если нет, то вот как мы можем использовать словарь Python для размещения формата запроса MongoDB:

# Query document where the `id` field is `3`
{"id":3}

# Query document where both `id` is `3` and `title` is `Special todo`
{"id":3, "title":"Special todo"}

# Query using special operator - Greater than Or Equal To, denoted with
# the dollar sign and name ($gte)
{"id" : {$gte : 5}}

Некоторые другие специальные операторы включают $eq , $ne , $gt , $lt , $lte и $non операторы.

Если вы не знакомы с ними, отличным местом, чтобы узнать о них больше, является официальная документация .

Теперь, когда мы рассмотрели задание запросов MongoDB для фильтрации метода find () , давайте посмотрим, как получить один документ, учитывая его _id :

@app.route("/get_todo/")
def insert_one(todoId):
    todo = db.todos.find_one({"_id": todoId})
    return todo

Итак, если бы мы отправили запрос GET в http://localhost:5000/get_todo/5 , мы получим следующий результат:

{
    "_id": 5,
    "body": "todo body six",
    "title": "todo title six"
}

Обратите внимание, что 5000 это порт сервера по умолчанию Flask , но его можно легко изменить при создании объекта Flask app

В большинстве случаев мы хотели бы получить товар или вернуть его. 404 ошибка, если элемент не был найден.

Flask-PyMongo предоставляет для этого вспомогательную функцию-метод find_one_or_404 () , который вызовет 404 ошибка, если запрошенный ресурс не был найден.

Обновление и замена документов

Чтобы обновить записи в нашей базе данных, мы можем использовать метод update_one() или replace_one() для изменения значения существующей сущности.

replace_one() имеет следующие аргументы:

  1. filter – Запрос, определяющий, какие записи будут заменены.
  2. замена – Записи, которые будут вставлены на их место при замене.
  3. {} – {} - Объект конфигурации, который имеет несколько вариантов, из которых будет сосредоточен на - расстроен

расстроенный , при установке значения true вставит замену в качестве нового документа, если в базе данных нет совпадений фильтров. И если есть совпадения, то он ставит замену вместо себя. Если расстроен если false и вы попытаетесь обновить документ, который не существует, ничего не произойдет.

Давайте посмотрим, как мы можем обновлять документы:

@app.route("/replace_todo/")
def replace_one(todoId):
    result = db.todos.replace_one({'_id': todoId}, {'title': "modified title"})
    return {'id': result.raw_result}
@app.route("/update_todo/")
def update_one(todoId):
    result = db.todos.update_one({'_id': todoId}, {"$set": {'title': "updated title"}})
    return result.raw_result

Итак, если бы мы отправили запрос в http://localhost:5000/update_todo/5 , мы получим следующий результат:

{
    "id": {
        "n": 1,
        "nModified": 1,
        "ok": 1.0,
        "updatedExisting": true
    }
}

Аналогично, если бы мы отправили запрос в http://localhost:5000/replace_todo/5 , мы получим следующий результат:

{
    "id": {
        "n": 1,
        "nModified": 1,
        "ok": 1.0,
        "updatedExisting": true
    }
}

Блок кода вернет объект Updated Result , с которым может быть немного утомительно работать. Именно поэтому Flask-PyMongo предоставляет более удобные методы, такие как find_one_and_update() и find_one_and_replace() – которые обновляют запись и возвращают ее:

@app.route("/replace_todo/")
def replace_one(todoId):
    todo = db.todos.find_one_and_replace({'_id': todoId}, {'title': "modified title"})
    return todo
@app.route("/update_todo/")
def update_one(todoId):
    result = db.todos.find_one_and_update({'_id': todoId}, {"$set": {'title': "updated title"}})
    return result

Итак, теперь, если бы мы послали запрос в http://localhost:5000/update_todo/5 , мы получим следующий результат:

{
    "_id": 5,
    "title": "updated title"
}

Аналогично, если бы мы отправили запрос в http://localhost:5000/replace_todo/5 , мы получим следующий результат:

{
    "_id": 5,
    "title": "modified title"
}

Flask-PyMongo также позволяет массовые обновления с помощью метода update_many() :

@app.route('/update_many')
def update_many():
    todo = db.todos.update_many({'title' : 'todo title two'}, {"$set": {'body' : 'updated body'}})
    return todo.raw_result

Приведенный выше кодовый блок найдет и обновит все записи с заголовком “todo title two” и приведет к:

Отправка запроса на наши новые конечные точки возвращает следующий результат:

{
    "n": 1,
    "nModified": 1,
    "ok": 1.0,
    "updatedExisting": true
}

Удаление документов

Как и другие, Flask-PyMongo предоставляет методы для удаления одной или нескольких записей с помощью методов delete_one() и delete_many() соответственно.

Аргументы этого метода те же, что и у других. Давайте рассмотрим пример:

@app.route("/delete_todo/", methods=['DELETE'])
def delete_todo(todoId):
    todo = db.todos.delete_one({'_id': todoId})
    return todo.raw_result

Это приведет к поиску и удалению записи с предоставленным идентификатором. Если мы отправили запрос DELETE вот так http://localhost:5000/delete_todo/5 к этой конечной точке мы получим следующий результат:

{
    "n": 1,
    "ok": 1.0
}

В качестве альтернативы можно использовать метод find_one_and_delete () , который удаляет и возвращает удаленный элемент, чтобы избежать использования объекта unhandy result:

@app.route("/delete_todo/", methods=['DELETE'])
def delete_todo(todoId):
    todo = db.todos.find_one_and_delete({'_id': todoId})
    if todo is not None:
        return todo.raw_result
    return "ID does not exist"

Отправка http://localhost:5000/delete_todo/8 к нашему серверу теперь приводит:

{
    "_id": 8,
    "body": "todo body two",
    "title": "todo title two"
}

Наконец, вы можете удалить его оптом, используя метод delete_many() :

@app.route('/delete_many', methods=['DELETE'])
def delete_many():
    todo = db.todos.delete_many({'title': 'todo title two'})
    return todo.raw_result

Отправка http://localhost:5000/delete_many к нашему серверу приведет что-то похожее на:

{
    "n": 1,
    "ok": 1.0
}

Сохранение и извлечение файлов

MongoDB позволяет нам сохранять двоичные данные в своей базе данных с помощью спецификации GridFS .

Flask-PyMongo предоставляет метод save_file() для сохранения файла в GridFS и метод send_file() для извлечения файлов из GridFS .

Начнем с маршрута загрузки файла в GridFS :

@app.route("/save_file", methods=['POST', 'GET'])
def save_file():
    upload_form = """

Save file



""" if request.method=='POST': if 'file' in request.files: file = request.files['file'] mongodb_client.save_file(file.filename, file) return {"file name": file.filename} return upload_form

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

Далее давайте посмотрим, как получить файл, который мы только что загрузили:

@app.route("/get_file/")
def get_file(filename):
    return mongodb_client.send_file(filename)

Этот блок кода вернет файл с заданным именем файла или вызовет ошибку 404, если файл не был найден.

Вывод

Расширение Flask-PyMongo предоставляет низкоуровневый API (очень похожий на официальный язык MongoDB) для связи с нашим экземпляром MongoDB.

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

В этой статье мы видели, как интегрировать MongoDB с нашим приложением Flask , мы также выполнили некоторые операции CRUD и видели, как работать с файлами с MongoDB с помощью GridFS .

Я постарался охватить как можно больше, но если у вас есть какие-либо вопросы и/или вклады, пожалуйста, оставьте комментарий ниже.