Browse Source

Replace MongoKit by MongoEngine on docs

Docs chapter "Patterns for Flask" has a section dedicated to MongoKit,
but MongoKit lib seems unmaintained and is not compatible with recent
versions of PyMongo.

This commit replaces MongoKit guide with a new one using MongoEngine.

Closes #2907
pull/2964/head
Igor Ghisi 6 years ago
parent
commit
2692cb7200
  1. 2
      docs/patterns/index.rst
  2. 140
      docs/patterns/mongoengine.rst
  3. 144
      docs/patterns/mongokit.rst

2
docs/patterns/index.rst

@ -34,7 +34,7 @@ Snippet Archives <http://flask.pocoo.org/snippets/>`_.
jquery jquery
errorpages errorpages
lazyloading lazyloading
mongokit mongoengine
favicon favicon
streaming streaming
deferredcallbacks deferredcallbacks

140
docs/patterns/mongoengine.rst

@ -0,0 +1,140 @@
.. mongoengine-pattern:
MongoEngine in Flask
====================
Using a document database rather than a full DBMS gets more common these days.
This pattern shows how to use MongoEngine, a document mapper library, to
integrate with MongoDB.
This pattern requires a running MongoDB server, MongoEngine_ and Flask-MongoEngine_
libraries installed::
pip install flask-mongoengine
.. _MongoEngine: http://mongoengine.org
.. _Flask-MongoEngine: http://docs.mongoengine.org/projects/flask-mongoengine/en/latest/>`_
Configuration
-------------
Basic setup can be done by defining ``MONGODB_SETTINGS`` on App config and then
creating a ``MongoEngine`` instance::
from flask import Flask
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
'host': "mongodb://localhost:27017/mydb"
}
db = MongoEngine(app)
Mapping Documents
-----------------
To declare models that will represent your Mongo documents, just create a class that
inherits from ``Document`` and declare each of the fields::
from mongoengine import *
class Movie(Document):
title = StringField(required=True)
year = IntField()
rated = StringField()
director = StringField()
actors = ListField()
If the model has embedded documents, use ``EmbeddedDocument`` to defined the fields of
the embedded document and ``EmbeddedDocumentField`` to declare it on the parent document::
class Imdb(EmbeddedDocument):
imdb_id = StringField()
rating = DecimalField()
votes = IntField()
class Movie(Document):
...
imdb = EmbeddedDocumentField(Imdb)
Creating Data
-------------
Just create the objects and call ``save()``::
bttf = Movie(title="Back To The Future", year=1985)
bttf.actors = [
"Michael J. Fox",
"Christopher Lloyd"
]
bttf.imdb = Imdb(imdb_id="tt0088763", rating=8.5)
bttf.save()
Queries
-------
Use the class ``objects`` attribute to make queries::
bttf = Movies.objects(title="Back To The Future").get() # Throw error if not unique
``objects`` is an iterable. Query operators may be user by concatenating it with the document
key using a double-underscore::
some_theron_movie = Movie.objects(actors__in=["Charlize Theron"]).first()
for recents in Movie.objects(year__gte=2017):
print(recents.title)
Available operators are as follows:
* ``ne`` -- not equal to
* ``lt`` -- less than
* ``lte`` -- less than or equal to
* ``gt`` -- greater than
* ``gte`` -- greater than or equal to
* ``not`` -- negate a standard check, may be used before other operators (e.g.
``Q(age__not__mod=5)``)
* ``in`` -- value is in list (a list of values should be provided)
* ``nin`` -- value is not in list (a list of values should be provided)
* ``mod`` -- ``value % x == y``, where ``x`` and ``y`` are two provided values
* ``all`` -- every item in list of values provided is in array
* ``size`` -- the size of the array is
* ``exists`` -- value for field exists
String queries
--------------
The following operators are available as shortcuts to querying with regular
expressions:
* ``exact`` -- string field exactly matches value
* ``iexact`` -- string field exactly matches value (case insensitive)
* ``contains`` -- string field contains value
* ``icontains`` -- string field contains value (case insensitive)
* ``startswith`` -- string field starts with value
* ``istartswith`` -- string field starts with value (case insensitive)
* ``endswith`` -- string field ends with value
* ``iendswith`` -- string field ends with value (case insensitive)
* ``match`` -- performs an $elemMatch so you can match an entire document within an array
Accessing PyMongo MongoClient
-----------------------------
If, for some reason, you want to access PyMongo instance, use ``get_connection`` function::
from mongoengine.connection import get_connection
conn = get_connection()
collection = conn.mydb.movie
collection({'title': u'Days of Thunder'})
For more information about MongoEngine, head over to the
`website <http://docs.mongoengine.org/>`_.

144
docs/patterns/mongokit.rst

@ -1,144 +0,0 @@
.. mongokit-pattern:
MongoKit in Flask
=================
Using a document database rather than a full DBMS gets more common these days.
This pattern shows how to use MongoKit, a document mapper library, to
integrate with MongoDB.
This pattern requires a running MongoDB server and the MongoKit library
installed.
There are two very common ways to use MongoKit. I will outline each of them
here:
Declarative
-----------
The default behavior of MongoKit is the declarative one that is based on
common ideas from Django or the SQLAlchemy declarative extension.
Here an example :file:`app.py` module for your application::
from flask import Flask
from mongokit import Connection, Document
# configuration
MONGODB_HOST = 'localhost'
MONGODB_PORT = 27017
# create the little application object
app = Flask(__name__)
app.config.from_object(__name__)
# connect to the database
connection = Connection(app.config['MONGODB_HOST'],
app.config['MONGODB_PORT'])
To define your models, just subclass the `Document` class that is imported
from MongoKit. If you've seen the SQLAlchemy pattern you may wonder why we do
not have a session and even do not define a `init_db` function here. On the
one hand, MongoKit does not have something like a session. This sometimes
makes it more to type but also makes it blazingly fast. On the other hand,
MongoDB is schemaless. This means you can modify the data structure from one
insert query to the next without any problem. MongoKit is just schemaless
too, but implements some validation to ensure data integrity.
Here is an example document (put this also into :file:`app.py`, e.g.)::
from mongokit import ValidationError
def max_length(length):
def validate(value):
if len(value) <= length:
return True
# must have %s in error format string to have mongokit place key in there
raise ValidationError('%s must be at most {} characters long'.format(length))
return validate
class User(Document):
structure = {
'name': unicode,
'email': unicode,
}
validators = {
'name': max_length(50),
'email': max_length(120)
}
use_dot_notation = True
def __repr__(self):
return '<User %r>' % (self.name)
# register the User document with our current connection
connection.register([User])
This example shows you how to define your schema (named structure), a
validator for the maximum character length and uses a special MongoKit feature
called `use_dot_notation`. Per default MongoKit behaves like a python
dictionary but with `use_dot_notation` set to ``True`` you can use your
documents like you use models in nearly any other ORM by using dots to
separate between attributes.
You can insert entries into the database like this:
>>> from yourapplication.database import connection
>>> from yourapplication.models import User
>>> collection = connection['test'].users
>>> user = collection.User()
>>> user['name'] = u'admin'
>>> user['email'] = u'admin@localhost'
>>> user.save()
Note that MongoKit is kinda strict with used column types, you must not use a
common `str` type for either `name` or `email` but unicode.
Querying is simple as well:
>>> list(collection.User.find())
[<User u'admin'>]
>>> collection.User.find_one({'name': u'admin'})
<User u'admin'>
.. _MongoKit: http://bytebucket.org/namlook/mongokit/
PyMongo Compatibility Layer
---------------------------
If you just want to use PyMongo, you can do that with MongoKit as well. You
may use this process if you need the best performance to get. Note that this
example does not show how to couple it with Flask, see the above MongoKit code
for examples::
from MongoKit import Connection
connection = Connection()
To insert data you can use the `insert` method. We have to get a
collection first, this is somewhat the same as a table in the SQL world.
>>> collection = connection['test'].users
>>> user = {'name': u'admin', 'email': u'admin@localhost'}
>>> collection.insert(user)
MongoKit will automatically commit for us.
To query your database, you use the collection directly:
>>> list(collection.find())
[{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}]
>>> collection.find_one({'name': u'admin'})
{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}
These results are also dict-like objects:
>>> r = collection.find_one({'name': u'admin'})
>>> r['email']
u'admin@localhost'
For more information about MongoKit, head over to the
`website <https://github.com/namlook/mongokit>`_.
Loading…
Cancel
Save