Like I described in the last post, I installed mongo and its python API mongoengine. Now I wanted to see if I could connect it to my preferred Python Web framework,
Django. A very nice
tutorial on IBM DeveloperWorks got me interested in trying this too.
I use Eclipse and the very nice
PyDev Python plug-in for Django development. The latter offers a little bit of
Django integration into Eclipse, so a had a bare-bones Django site in no time at all, with the standard settings.py file. At this point, the site was based on SqlLite, Django's default.
Now the first bit is to connect to MongoDB inside settings.py, following the
Mongoengine tutorial, like so:
import mongoengine
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
# ('Your Name', 'your_email@example.com'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'C:\\Users\\me\\src\\test\\django_mongo\\sqlite.db', # Or path to database file if using sqlite3.
# The following settings are not used with sqlite3:
'USER': '',
'PASSWORD': '',
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '', # Set to empty string for default.
}
}
print 'Connection to MongoDB...',
mongoengine.connect('test')
print 'connected.'
Additional lines that go to the bottom of settings.py are
AUTHENTICATION_BACKENDS = (
'mongoengine.django.auth.MongoEngineBackend',
)
SESSION_ENGINE = 'mongoengine.django.sessions'
At this point I was able to run the Django shell, but of course had no models to play with. So I made an app with the standard Django manage.py startapp replicated the ones from the tutorial, except for the User model, which I imported from the mongoengine auth backend:
from mongoengine import *
from mongoengine.django.auth import User
# Create your models here.
class Comment(EmbeddedDocument):
content = StringField()
name = StringField(max_length=120)
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))
class TextPost(Post):
content = StringField()
class ImagePost(Post):
image_path = StringField()
class LinkPost(Post):
link_url = StringField()
Back in the Django shell, I got some FutureWarnings regarding inheritance soon defaulting to off, but I successfully tested
In [2]: c=Comment(content='lala', name='Useful comment')
In [3]: u=User()
In [4]: u.username='me'
...
In [30]: u
Out[30]: <User: me>
In [31]: User.objects.all()
Out[31]: []
In [32]: u.save()
Out[32]: <User: me>
In [33]: User.objects.all()
Out[33]: [<User: me>]
In [35]: p=Post(title='T', author=u, tags=['t1','t2'], comments=[c])
In [36]: p.save()
Out[36]: <Post: Post object>
In [38]: Post.objects.all()
Out[38]: [<Post: Post object>]
In [39]: Post.objects.all()[0]
Out[39]: <Post: Post object>
In [40]: Post.objects.all()[0].comments
Out[40]: [<Comment: Comment object>]
In [41]: Post.objects.filter(title='A')
Out[41]: []
In [42]: Post.objects.filter(title='T')
Out[42]: [<Post: Post object>]
In [43]: Post.objects.filter(title__in=['A','T'])
Out[43]: [<Post: Post object>]
But I did get stuck at joins that span relations:
In [54]: Post.objects.filter(author__username='me')
Out[54]: ---------------------------------------------------------------------------
InvalidQueryError Traceback (most recent call last)
Either I got something wrong or a bug tripped me! I will definitely crosspost this at Mongoengine and StackOverflow.
BTW, this was done with Django 1.6 20130110 dev trunk and Mongoengine 0.7.9 .