====== MongoEngine ====== It's a MongoDB ORM for Python. ===== First steps ===== ==== Installation and import ==== $ pip install mongoengine To start using MongoEngine we will import like this: import mongoengine ==== Connecting to a DB ==== To connect a DB we will use the ''connect'' function, its first argument is the DB: connect('project1') connect('project1', host='192.168.1.35', port=12345) connect('project1', username='webapp', password='pwd123') connect('project1', host='mongodb://localhost/database_name') ===== Defining the schema ===== ==== In a nutshell ==== Next schema implements a Blog where a User can create different type Posts. Those types are inherited classes from Post. class User(Document): email = StringField(required=True) first_name = StringField(max_length=50) last_name = StringField(max_length=50) class Post(Document): title = StringField(max_length=120, required=True) author = ReferenceField(User) meta = {'allow_inheritance': True} class TextPost(Post): content = StringField() class ImagePost(Post): image_path = StringField() class LinkPost(Post): link_url = StringField() === Other field objects === * ''tags = ListField(StringField(max_length=30))'', a ''ListField'' is a field object that allows to have a list of other field objects (including other lists). * ''date_modified = DateTimeField(default=datetime.datetime.now)'' More about this subject in: [[http://docs.mongoengine.org/guide/defining-documents.html#fields]] ==== Storing an object ==== Comment.objects.create(text='Me gusta!') ==== Storing an object inside another ==== class Comment(EmbeddedDocument): content = StringField() name = StringField(max_length=120) class Post(Document): title = StringField(max_length=120, required=True) author = ReferenceField(User) tags = ListField(StringField(max_length=30)) comments = ListField(EmbeddedDocumentField(Comment)) We also could use ''GenericReferenceField'' to reference any kind of document: class Bookmark(Document): bookmark_object = GenericReferenceField() ==== Cascade delete ==== When we define a ''ReferenceField'' we can indicate ''reverse_delete_rule=CASCADE'' to delete all the objects when a referenced object is deleted (it does not work with MapFields neither DictFields). class Post(Document): title = StringField(max_length=120, required=True) author = ReferenceField(User, reverse_delete_rule=CASCADE) tags = ListField(StringField(max_length=30)) comments = ListField(EmbeddedDocumentField(Comment)) Other constans we can pass: * ''mongoengine.DO_NOTHING'' * ''mongoengine.DENY'' * ''mongoengine.NULLIFY'' * ''mongoengine.CASCADE'' * ''mongoengine.PULL'' ==== Dynamic documents ==== DynamicDocument documents work like Document but any data or attributes set to them will also be saved (fields cannot start with _ ). from mongoengine import * class Page(DynamicDocument): title = StringField(max_length=200, required=True) # Create a new page and add tags page = Page(title='Using MongoEngine') page.tags = ['mongodb', 'mongoengine'] page.save() ==== Defining constraints ==== We can specify field uniqueness with ''unique=True'' and multi-fielduniqueness with ''unique_with'' (for a field name, or a list, or a tuple): class User(Document): username = StringField(unique=True) first_name = StringField() last_name = StringField(unique_with='first_name') ===== Editing Data ===== ==== Adding documents ==== ross = User(email='ross@example.com', first_name='Ross', last_name='Lawley').save() # this is other way to save ross ross1 = User(email='ross1@example.com') ross1.first_name = 'Ross1' ross1.last_name = 'Lawley' ross1.save() post1 = TextPost(title='Fun with MongoEngine', author=john) post1.content = 'Took a look at MongoEngine today, looks pretty cool.' post1.tags = ['mongodb', 'mongoengine'] post1.save() post2 = LinkPost(title='MongoEngine Documentation', author=ross) post2.link_url = 'http://docs.mongoengine.com/' post2.tags = ['mongoengine'] post2.save() ===== Accessing data ===== A ''Document'' object is actually a ''QuerySet'' object. It lazily queries the database when you need the data. ''QuerySet'' objects perform searches on the data base using functions like... * ''first()'' to retrieve the first object that matches with the provided query. * ''count()'' to know the number of objects that matche with the provided query. ==== Examples ==== === Retrieving all the post titles === for post in Post.objects: print post.title === Retrieving a concrete type content === for post in TextPost.objects: print post.content === Searching by tag === for post in Post.objects(tags='mongodb'): print post.title ===== Others ===== ==== Django support ==== === Connecting === You only need to call ''connect()'' somewhere in the settings module. If you were not using another Database backend you may need to add a dummy database: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.dummy' } } === Users === Django authentication classes are included as Document classes so they are compatible. To enable them you should add the following to your settings.py file: AUTHENTICATION_BACKENDS = ( 'mongoengine.django.auth.MongoEngineBackend', ) Remember to call ''set_password()'' method in ''User'' class when assign a password value: instance.set_password(attrs.get('password', instance.password))