django-mongonaut¶
This is an introspective interface for Django and MongoDB. Built from scratch to replicate some of the Django admin functionality, but for MongoDB.
Contents:
Installation¶
Normal Installation¶
Get MongoDB:
Download the right version per http://www.mongodb.org/downloads
Get the code:
pip install django-mongonaut==0.2.20
Install the dependency in your settings file (settings.py):
INSTALLED_APPS = (
...
'mongonaut',
...
)
Add the mongonaut urls.py file to your urlconf file:
urlpatterns = patterns('',
...
url(r'^mongonaut/', include('mongonaut.urls')),
...
)
Also in your settings file, you’ll need something like:
# mongodb connection
from mongoengine import connect
connect('example_blog')
You will need the following also set up:
- django.contrib.sessions
- django.contrib.messages
Note
No need for autodiscovery() with django-mongonaut!
Static Media Installation¶
By default, django-mongonaut uses static media hosted by other services such as Google or Github. If you need to point to another location, then you can change the following defaults to your new source:
# settings.py defaults
MONGONAUT_JQUERY = "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"
MONGONAUT_TWITTER_BOOTSTRAP = "http://twitter.github.com/bootstrap/assets/css/bootstrap.css"
MONGONAUT_TWITTER_BOOTSTRAP_ALERT = http://twitter.github.com/bootstrap/assets/js/bootstrap-alert.js"
Heroku MongoDB connection via MongoLabs¶
Your connection string will be provided by MongoLabs in the Heroku config. To make that work, just use the following code instead the # mongodb connection example:
# in your settings file (settings.py)
import os
import re
from mongoengine import connect
regex = re.compile(r'^mongodb\:\/\/(?P<username>[_\w]+):(?P<password>[\w]+)@(?P<host>[\.\w]+):(?P<port>\d+)/(?P<database>[_\w]+)$')
mongolab_url = os.environ['MONGOLAB_URI']
match = regex.search(mongolab_url)
data = match.groupdict()
connect(data['database'], host=data['host'], port=int(data['port']), username=data['username'], password=data['password'])
Configuration¶
One of the most useful parts of django.contrib.admin is the ability to configure various views that touch and alter data. django-mongonaut is similar to the Django Admin, but adds in new functionality and ignores other features. The reason is that MongoDB is not a relational database, so attempting to replicate in general simply removes some of the more useful features we get from NoSQL.
Basic Pattern¶
In your app, create a module called ‘mongoadmin.py’. It has to be called that or django-mongonaut will not be able to find it. Then, in your new mongonaut file, simply import the mongoengine powered models you want mongonaut to touch, then import the MongoAdmin class, instantiate it, and finally attach it to your model.
# myapp/mongoadmin.py
# Import the MongoAdmin base class
from mongonaut.sites import MongoAdmin
# Import your custom models
from blog.models import Post
# Instantiate the MongoAdmin class
# Then attach the mongoadmin to your model
Post.mongoadmin = MongoAdmin()
That’s it! Now you can view, add, edit, and delete your MongoDB models!
Note
You will notice a difference between how and django.contrib.admin and django-mongonaut do configuration. The former associates the configuration class with the model object via a registration utility, and the latter does so by adding the configuration class as an attribute of the model object.
More details and features are available in the API reference document.
API¶
The following are advanced configuration features for django-mongonaut. Using them requires you to subclass the mongonaut.MongoAdmin class, then instantiate and attach your subclass as an attribute to the MongoEngine model.
Note
Future versions of mongonaut will allow you to work with pymongo collections without mongoengine serving as an intermediary.
MongoAdmin Objects¶
class MongoAdmin¶
The MongoAdmin class is the representation of a model in the mongonaut interface. These are stored in a file named mongoadmin.py in your application. Let’s take a look at a very simple example of the MongoAdmin:
# myapp/mongoadmin.py
# Import the MongoAdmin base class
from mongonaut.sites import MongoAdmin
# Import your custom models
from blog.models import Post
# Subclass MongoAdmin and add a customization
class PostAdmin(MongoAdmin):
# Searches on the title field. Displayed in the DocumentListView.
search_fields = ('title',)
# provide following fields for view in the DocumentListView
list_fields = ('title', "published", "pub_date")
# Instantiate the PostAdmin subclass
# Then attach PostAdmin to your model
Post.mongoadmin = PostAdmin()
MongoAdmin Options¶
The MongoAdmin is very flexible. It has many options for dealing with customizing the interface. All options are defined on the MongoAdmin subclass:
has_add_permission¶
default:
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
def has_add_permission(self, request):
""" Can add this object """
return request.user.is_authenticated and request.user.is_active and request.user.is_staff)
has_edit_permission¶
default:
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
def has_delete_permission(self, request):
""" Can delete this object """
return request.user.is_authenticated and request.user.is_active and request.user.is_admin()
has_edit_permission¶
default:
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
def has_edit_permission(self, request):
""" Can edit this object """
return request.user.is_authenticated and request.user.is_active and request.user.is_staff)
has_view_permission¶
default:
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
def has_view_permission(self, request):
""" Can view this object """
return request.user.is_authenticated and request.user.is_active
list_fields¶
default: Mongo _id
Accepts an iterable of string fields that matches fields in the associated model. Displays these fields as columns.
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
# provide following fields for view in the DocumentListView
list_fields = ('title', "published", "pub_date")
search_fields¶
default: []
Accepts an iterable of string fields that matches fields in the associated model. Displays a search field in the DocumentListView. Performs an ‘icontains’ search with an ‘OR’ between evaluations.
# myapp/mongoadmin.py
class PostAdmin(MongoAdmin):
# Searches on the title field. Displayed in the DocumentListView.
search_fields = ('title',)
Future Usage Concepts¶
Warning
This is is not implemented. It’s sort of my dream of what I want this project to be able to do.
Complex version. Create a mongonaut.py module in your app:
#myapp.mongonaut
from datetime import datetime
from mongonaut.sites import MongoAdmin
from blog.models import Post
class ArticleAdmin(MongoAdmin):
search_fields = ['title',]
#This shows up on the DocumentListView of the Posts
list_actions = [publish_all_drafts,]
# This shows up in the DocumentDetailView of the Posts.
document_actions = [generate_word_count,]
field_actions = {confirm_images: 'image'}
def publish_all_drafts(self):
""" This shows up on the DocumentListView of the Posts """
for post in Post.objects.filter(published=False):
post.published = True
post.pub_date = datetime.now()
post.save()
def generate_word_count(self):
""" This shows up in the DocumentDetailView of the Posts.
ID in this case is somehow the ID of the Posting objecy
"""
return len(Post.objects.get(self.id).content.split(' '))
def confirm_images(self):
""" This will be attached to a field in the generated form
specified in a dictionary
"""
do_xyz()
# TODO write this code or something like it
Article.mongoadmin = ArticleAdmin()
. include:: ../contributing.md
Features¶
Introspection of mongoengine data¶
- Introspection via mongo engine
- Q based searches
- django.contrib.admin style browsing
- Automatic detection of field types
- Automatic discovery of collections
Introspection of pymongodata¶
[in progress] Admin determination of which fields are displayed. Currently they can do so in the Document List view but not the Document Detail view.
[in progress] Introspection via pymongo. This is becoming very necessary. Plan:
- Always guarantee the _id.
- Allow devs to set 1 or more field as ‘expected’. But there is no hard contract!
- introspect on field types to match how pymongo pulls data. So a str is handled differently than a list field.
Data Management¶
- [in progress] Admin authored Collection level document control functions
- EmbeddedDocumentsFields
- Editing on ListFields
- Document Deletes
- Editing on most other fields including ReferenceFields.
- Automatic detection of widget types
- Text field shorthand for letting user quickly determine type when using without mongoengine
- Document Adds
Permissions¶
- [in progress] Group defined controls
- User level controls
- Staff level controls
- Admin defined controls