Руководство по использованию механизма Django MongoDB с Python

Введение В этой статье мы увидим, как использовать MongoDB, нереляционную базу данных, с Django, веб-платформой Python. Django обычно используется с PostgreSQL, MariaDB или MySQL, всеми реляционными базами данных, из-за того, что под капотом находится ORM. MongoDB, будучи довольно гибким, обычно сочетается с легкими фреймворками, такими как Flask, для упрощения прототипирования. Однако он также все чаще используется в более крупных проектах из-за масштабируемости, динамических структур и поддержки запросов. > Джанго Мон

Вступление

В этой статье мы увидим, как использовать MongoDB, нереляционную базу данных, с Django, веб-платформой Python.

Django обычно используется с PostgreSQL, MariaDB или MySQL, всеми реляционными базами данных, из-за того, что под капотом находится ORM. MongoDB, будучи довольно гибким, обычно сочетается с легкими фреймворками, такими как Flask, для упрощения прототипирования. Однако он также все чаще используется в более крупных проектах из-за масштабируемости, динамических структур и поддержки запросов.

Django MongoDB Engine используется для декларативного определения схем.

Примечание. На момент написания этот движок не поддерживает Python 3.x. Последняя поддерживаемая версия - Python 2.7 .

Нереляционные и реляционные базы данных

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

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

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

Реляционная база данных

Реляционная база данных хранит данные в таблицах, которые состоят из столбцов и строк.

  • Строка представляет объект (например, Movie )
  • Столбец представляет атрибут объекта (например, name фильма, его length , year выпуска и т. Д.)
  • Строка представляет одну запись в базе данных (например, {"The Matrix", 2h 16min, 1999.} ).

Каждая строка таблицы должна иметь уникальный ключ ( идентификатор ), который представляет только эту строку.

Некоторые из самых известных реляционных баз данных: Oracle, PostgreSQL, MySQL и MariaDB .

Нереляционная база данных

Нереляционная база данных не хранит данные в таблицах, это зависит от типа данных. Существует четыре различных типа нереляционных баз данных:

  • Документно-ориентированная база данных (или хранилище документов)
    • Управляет набором именованных строковых полей, обычно в форме документов JSON, XML или YAML. Эти форматы также могут иметь производные.
  • Магазин ширококолонный
    • Организует данные в столбцы по структуре, аналогичной реляционным базам данных.
  • Магазин Graph
    • Хранит отношения между сущностями (самый сложный тип нереляционной базы данных)
    • Используется, когда данные широко взаимосвязаны
  • Хранилище ключей и значений
    • Простая коллекция пар "ключ-значение"

Некоторые из самых известных нереляционных баз данных: MongoDB, Cassandra, Redis .

реляционные и нереляционные базыданных{.ezlazyload}

MongoDB является документ , на основе не-реляционная база данных, которая сохраняет документы в формате BSON (Binary JSON) - это производная JSON.

Установка и настройка

Чтобы реализовать Django MongoDB Engine в проекте, нам нужно установить три вещи:

  1. Django-nonrel - Поддержка нереляционных баз данных (при этом также будет установлен Django 1.5 и удалена любая ранее установленная версия).
  2. djangotoolbox - Инструменты для нереляционных приложений Django.
  3. Django MongoDB Engine - сам движок.

Давайте установим их через pip вместе с самим Django:

 $ pip install django 
 $ pip install git+https://github.com/django-nonrel/ [email protected] 
 $ pip install git+https://github.com/django-nonrel/djangotoolbox 
 $ pip install git+https://github.com/django-nonrel/mongodb-engine 

Давайте инициализируем проект Django через командную строку, чтобы получить отправную точку:

 $ django-admin.py startproject djangomongodbengine 

Теперь, имея скелетный проект, содержащий некоторые базовые файлы, мы хотим сообщить Django, какой движок мы хотим использовать. Для этого мы обновим наш settings.py и, в частности, свойство DATABASES

 DATABASES = { 
 'default' : { 
 'ENGINE' : 'django_mongodb_engine', 
 'NAME' : 'example_database' 
 } 
 } 

После завершения установки и настройки давайте взглянем на некоторые вещи, которые мы можем делать с помощью Django MongoDB Engine.

Модели и поля

Когда дело доходит до работы с моделями , в стандартной архитектуре MVC (модель-представление-контроллер) классический подход заключается в использовании модуля django.db.models Класс Model имеет CharField s, TextField s и т. Д., Которые позволяют вам по существу определять схему ваших моделей и то, как они будут отображаться в базе данных ORM Django.

Давайте добавим Movie в наш models.py :

 from django.db import models 
 
 class Movie(models.Model) 
 name = models.CharField() 
 length = models.IntegerField() 

Здесь у нас есть Movie с двумя полями - name и length . Каждый из них является Field , представляющего столбец базы данных с заданным типом данных.

Хотя существует довольно много типов полей , models не имеет большой поддержки для полей с несколькими значениями.

В основном это связано с тем, что models предназначен в основном для использования с реляционными базами данных. Когда у объекта есть поле с несколькими значениями, например Movie имеющий много Actor s, у вас будет связь « один ко многим» с другой таблицей.

С MongoDB вы можете сохранить их в виде списка в этом документе без необходимости делать ссылку базы данных на другую таблицу или документ. Именно здесь мы чувствуем нехватку таких полей, как ListField и DictField .

ListField

ListField - это атрибут типа списка, атрибут, который может содержать несколько значений. Он принадлежит djangotoolbox.fields и может использоваться для указания полей, содержащих значения в виде списка, которые затем сохраняются в документе BSON.

Давайте настроим нашу Movie из предыдущего:

 from django.db import models 
 from djangotoolbox.fields import ListField 
 
 class Movie(models.Model): 
 name = models.CharField() 
 length = models.IntegerField() 
 year = models.IntegerField() 
 actors = ListField() 

Обратите внимание, что мы не указали поле id В этом нет необходимости, поскольку MongoDB неявно назначит его экземпляру Model . Кроме того, мы добавили actors , которое является ListField .

Теперь при создании Movie мы можем назначить список actors и сохранить его в нашей базе данных MongoDB как есть, не создавая отдельной таблицы, содержащей Actor и ссылаясь на них в наших документах Movie

 movie = Movie.objects.create( 
 name = "The Matrix", 
 length = 136, 
 year = 1999, 
 actors = ["Keanu Reeves", "Laurence Fishburne"] 
 ) 

Запуск этого фрагмента кода приводит к созданию документа MongoDB:

 { 
 "_id" : ObjectId("..."), 
 "name" : "The Matrix", 
 "length" : 136, 
 "year" : 1999, 
 "actors" : [ 
 "Keanu Reeves", 
 "Laurence Fishburne" 
 ] 
 } 

Мы также можем ListField extend() ListField и добавить к нему дополнительные значения:

 movie.actors.extend(['Carrie-Ann Moss']) 

Это приводит к обновленному документу BSON:

 { 
 "_id" : ObjectId("..."), 
 "name" : "The Matrix", 
 "length" : 136, 
 "year" : 1999, 
 "actors" : [ 
 "Keanu Reeves", 
 "Laurence Fishburne", 
 "Carrie-Ann Moss", 
 "Carrie-Ann Moss" 
 ] 
 } 

SetField

SetField - это то же самое, что и ListField за исключением того, что он интерпретируется как набор Python, что означает, что дублирование не допускается.

Если мы добавим одного и того же актера дважды:

 movie.actors.extend(['Carrie-Ann Moss']) 

Мы быстро понимаем, что результат немного странный:

 { 
 "_id" : ObjectId("..."), 
 "name" : "The Matrix", 
 "length" : 136, 
 "year" : 1999, 
 "actors" : [ 
 "Keanu Reeves", 
 "Laurence Fishburne", 
 "Carrie-Ann Moss" 
 ] 
 } 

Поскольку мы хотели бы избежать дублирования записей, чтобы каждый человек оставался фактическим человеком, имеет смысл сделать actors SetField вместо ListField :

 from django.db import models 
 from djangotoolbox.fields import ListField 
 
 class Movie(models.Model): 
 name = models.CharField() 
 length = models.IntegerField() 
 year = models.IntegerField() 
 actors = SetField() 

Теперь мы можем добавить несколько актеров, некоторые из которых являются дубликатами, и у нас будут только уникальные дополнения:

 movie = Movie.objects.create( 
 name = "John Wick", 
 length = 102, 
 year = 2014, 
 actors = ["Keanu Reeves", "Keanu Reeves", "Bridget Moynahan"] 
 ) 

Однако в итоговом документе будет только одна запись для "Keanu Reeves" , единственная и неповторимая:

 { 
 "_id" : ObjectId("..."), 
 "name" : "John Wick", 
 "length" : 102, 
 "year" : 2014, 
 "actors" : [ 
 "Keanu Reeves", 
 "Bridget Moynahan" 
 ] 
 } 

DictField

DictField хранит словари Python как еще один документ BSON в вашем собственном документе. Это предпочтительнее, если вы не уверены, как может выглядеть словарь - и у вас нет для него заранее определенной структуры.

С другой стороны, если структура знакома, рекомендуется использовать встроенные модели в качестве моделей внутри моделей. Например, Actor может быть модель сама по себе, и мы могли бы позволить Movie модель имеет несколько встроенных Actor моделей. С другой стороны, если необходимо добавить переменный набор значений, они могут быть отображены как элементы «ключ-значение» и сохранены через DictField .

Например, добавим reviews , в котором может быть 0..n отзывов. Хотя reviews имеют предсказуемую структуру ( name , grade , comment ), мы реализуем их как DictField , прежде чем сделать отдельную Model для actors и reviews :

 from django.db import models 
 from djangotoolbox.fields import SetField 
 from djangotoolbox.fields import DictField 
 
 class Movie(models.Model): 
 name = models.CharField() 
 length = models.IntegerField() 
 year = models.IntegerField() 
 actors = SetField() 
 reviews = DictField() 

Теперь при создании фильмов мы можем добавлять словари рецензентов и их рецензии на фильмы:

 movie = Movie.objects.create( 
 name = "Good Will Hunting", 
 length = 126, 
 year = 1997, 
 actors = ["Matt Damon", "Stellan Skarsgard"], 
 reviews = [ 
 {"Portland Oregonian" : "With its sweet soul and sharp mind..."}, 
 {"Newsweek" : "Gus Van Sant, working from the tangy, well-written script..."} 
 ] 
 ) 

Выполнение этого кода приводит к:

 { 
 "_id" : ObjectId("..."), 
 "name" : "Good Will Hunting", 
 "length" : 126, 
 "year" : 1997, 
 "actors" : [ 
 "Matt Damon", 
 "Stellan Skarsgard" 
 ], 
 "reviews" : [ 
 {"Portland Oregonian" : "With its sweet soul and sharp mind..."}, 
 {"Newsweek": "Gus Van Sant, working from the tangy, well-written script..."} 
 ] 
 } 

Встроенные модели

Теперь reviews , возможно, будет иметь такую же структуру - name за которым следует comment . actors - это больше, чем просто их имена - у них есть last_name , date_of_birth и другие характеристики.

Для обоих из них мы можем создавать автономные модели, как если бы мы делали это с реляционными базами данных. Однако с реляционными базами данных мы сохраняли бы их в их собственных таблицах и связывали бы с ними из таблицы Movie

С помощью MongoDB мы можем превратить их во встроенные модели - целые документы, встроенные в другой документ.

Давайте еще раз изменим наш Movie :

 from django.db import models 
 from djangotoolbox.fields import ListField, EmbeddedModelField 
 
 
 class Movie(models.Model): 
 name = models.CharField(max_length=100) 
 length = models.IntegerField() 
 year = models.IntegerField() 
 actors = SetField(EmbeddedModelField("Actor")) 
 reviews = SetField(EmbeddedModelField("Review")) 

Здесь мы создали SetField (который также мог быть чем-то вроде ListField ) как для actors и для reviews . Однако на этот раз мы сделали их SetField из других моделей , передав EmbeddedModelField в конструкторы SetField .

Мы также указали, какие модели в конструкторе класса EmbeddedModelField

Теперь давайте определим и эти два в файле models.py

 class Actor(models.Model): 
 first_name = models.CharField(max_length=30) 
 last_name = models.CharField(max_length=30) 
 date_of_birth = models.CharField(max_length=11) 
 
 class Review(models.Model): 
 name = models.CharField(max_length=30) 
 comment = models.CharField(max_length=300) 

Теперь, при создании Movie и сохранении его в базе данных, мы также можем добавить к нему новые экземпляры Actor и Review

 movie = Movie.objects.create( 
 name = "Focus", 
 length = 105, 
 year = 2015, 
 actors = [ 
 Actor( 
 first_name="Will", 
 last_name="Smith", 
 date_of_birth="25.09.1968." 
 ) 
 ], 
 reviews = [ 
 Review( 
 name = "Portland Oregonian", 
 comment = "With its sweet soul and sharp mind..." 
 ), 
 Review( 
 name = "Newsweek", 
 comment = "Gus Van Sant, working from the tangy, well-written script..." 
 ) 
 ] 
 ) 

Это создает новые документы BSON для каждого Actor и Review в наборах и сохраняет их как встроенные объекты в наш документ movie

 { 
 "_id" : ObjectId("..."), 
 "name" : "Focus", 
 "length" : 105, 
 "year" : 2015, 
 "actors" : [ 
 { 
 "name" : "Will", 
 "last_name" : "Smith", 
 "date_of_birth" : "25.09.1968" 
 } 
 ], 
 "reviews" : [ 
 { 
 "name" : "Portland Oregonian", 
 "comment" : "With its sweet soul and sharp mind..." 
 }, 
 { 
 "name" : "Newsweek", 
 "comment" : "Gus Van Sant, working from the tangy, well-written script..." 
 } 
 ] 
 } 

Каждая запись в массиве BSON reviews является отдельным экземпляром Review То же самое и с actors .

Обработка файлов

MongoDB имеет встроенную спецификацию для хранения / извлечения файлов в файловой системе под названием GridFS , которая также используется в Django MongoDB Engine.

Примечание. MongoDB хранит файлы, разделяя их на части размером 255 kB каждая. При доступе к файлу GridFS собирает части и объединяет их.

Чтобы импортировать систему django_mongodb_engine_storage модулю django_mongodb_engine_storage:

 from django_mongodb_engine.storage import GridFSStorage 
 
 gridfs = GridFSStorage() 
 uploads_location = GridFSStorage(location = '/uploaded_files') 

Еще одно поле, которое мы можем использовать, - это GridFSField() , которое позволяет нам указывать поля, которые используют систему GridFS для хранения данных:

 class Movie(models.Model): 
 name = models.CharField() 
 length = models.IntegerField() 
 year = models.IntegerField() 
 actors = SetField(EmbeddedModelField("Actor")) 
 reviews = SetField(EmbeddedModelField("Review")) 
 poster = GridFSField() 

Теперь это изображение будет сохраняться кусками и загружаться лениво только по запросу.

Заключение

Подводя итог, можно сказать, что Django MongoDB Engine - довольно мощный движок, и основным недостатком его использования является то, что он работает со старыми версиями Django (1.5) и Python (2.7), тогда как Django теперь имеет 3,2 LTS и поддерживает 1,5. закончился давным-давно. Python находится на уровне 3.9, а поддержка 2.7 закончилась в прошлом году. Вдобавок ко всему, Django MongoDB Engine, похоже, прекратил дальнейшую разработку еще в 2015 году.

comments powered by Disqus