mirror of https://github.com/mitsuhiko/flask.git
Browse Source
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 #2907pull/2964/head
Igor Ghisi
6 years ago
3 changed files with 141 additions and 145 deletions
@ -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/>`_. |
@ -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…
Reference in new issue