Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

final bis of documentation written, minor change to SessionMixin to e…

…nsure model creation on access if empty.
  • Loading branch information...
commit 6319d115ee2218637323c346f80b92df3e1b6704 1 parent a05548a
@LBiNationalTrust LBiNationalTrust authored
Showing with 1,253 additions and 84 deletions.
  1. BIN  Documentation/_build/doctrees/docs/apps.doctree
  2. BIN  Documentation/_build/doctrees/docs/authentication.doctree
  3. BIN  Documentation/_build/doctrees/docs/models.doctree
  4. BIN  Documentation/_build/doctrees/docs/quickstart.doctree
  5. BIN  Documentation/_build/doctrees/docs/socketio.doctree
  6. BIN  Documentation/_build/doctrees/docs/urls.doctree
  7. BIN  Documentation/_build/doctrees/docs/views.doctree
  8. BIN  Documentation/_build/doctrees/environment.pickle
  9. BIN  Documentation/_build/doctrees/index.doctree
  10. +21 −2 Documentation/_build/html/_sources/docs/apps.txt
  11. +88 −2 Documentation/_build/html/_sources/docs/authentication.txt
  12. +166 −2 Documentation/_build/html/_sources/docs/models.txt
  13. +6 −3 Documentation/_build/html/_sources/docs/quickstart.txt
  14. +71 −2 Documentation/_build/html/_sources/docs/socketio.txt
  15. +15 −0 Documentation/_build/html/_sources/docs/urls.txt
  16. +65 −0 Documentation/_build/html/_sources/docs/views.txt
  17. +1 −1  Documentation/_build/html/_sources/index.txt
  18. +4 −4 Documentation/_build/html/docs/api/Auth.html
  19. +24 −8 Documentation/_build/html/docs/apps.html
  20. +108 −7 Documentation/_build/html/docs/authentication.html
  21. +159 −8 Documentation/_build/html/docs/models.html
  22. +10 −8 Documentation/_build/html/docs/quickstart.html
  23. +83 −12 Documentation/_build/html/docs/socketio.html
  24. +23 −9 Documentation/_build/html/docs/urls.html
  25. +184 −0 Documentation/_build/html/docs/views.html
  26. +21 −5 Documentation/_build/html/index.html
  27. BIN  Documentation/_build/html/objects.inv
  28. +1 −1  Documentation/_build/html/searchindex.js
  29. +88 −2 Documentation/docs/authentication.rst
  30. +0 −3  Documentation/docs/backends.rst
  31. +23 −0 Documentation/docs/models.rst
  32. +71 −2 Documentation/docs/socketio.rst
  33. +15 −0 Documentation/docs/urls.rst
  34. +0 −1  Documentation/index.rst
  35. +2 −0  Mojo/Auth/Mixins/SessionMixins.py
  36. +4 −2 Mojo/SocketHandlers/BaseSocketHandler.py
View
BIN  Documentation/_build/doctrees/docs/apps.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/authentication.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/models.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/quickstart.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/socketio.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/urls.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/docs/views.doctree
Binary file not shown
View
BIN  Documentation/_build/doctrees/environment.pickle
Binary file not shown
View
BIN  Documentation/_build/doctrees/index.doctree
Binary file not shown
View
23 Documentation/_build/html/_sources/docs/apps.txt
@@ -1,3 +1,22 @@
-What are apps
-=============
+Mojo Apps
+=========
+
+When developing with Mojo, it's more elegant to modularise functionality into Apps, and this is the default behaviour
+of the Mojo server loader.
+
+Apps serve as a collection of RequestHandlers, URL Mappings, Models and Templates that make up a set of functionality
+in your project.
+
+To get started with an app in your project, you can use the ``mojo_manager.py`` helper application that will auto create
+your project folder for you::
+
+ python mojo_manager.py -a [YOUR_APP_NAME]
+
+This will create an app folder with certain key files:
+
+- ``models.py``: This is where you define your models which can be used with your database and forms
+- ``socket_handlers.py``: This is where you define your SocketIO behaviour, each app has it's own dedicated (multiplexed) channel under ``/[appname]Socket`` to separate out functionality
+- ``ui_modules.py``: The ui_modules you might or mihjgt not be using
+- ``urls.py``: The URL mappings for your request handlers
+- ``views.py``: A list of your ``RequestHandler`` classes that handle your app functionality
View
90 Documentation/_build/html/_sources/docs/authentication.txt
@@ -1,3 +1,89 @@
-Using Mojo's Auth module
-========================
+Using Mojo's Auth and Session Mixins
+====================================
+
+To make Tornado a bit easier to use and integrate with your application, Mojo provides a sesison management mixin that
+adds database-backed sessions to your requests.
+
+The Session Mixin assumes that a database backend and ORM is present, which is why it comes in both sync and async flavors.
+The AuthMixin does not assume that a database is present and solely uses the set_cookie functionality of Tornado to make
+the get_current_user functionality work.
+
+AuthMixin
+---------
+
+The AuthMixin basically overrides get_current_user() in the MojoRequestHandler and adds a SessionManager object to the
+attributes of the RequestHandler. Using the SessionManager, it is possible to login/logout the user::
+
+ if thisUser is not None:
+ if is_authenticated:
+ SessionManager(request)._login(thisUser) #Will make the relevant changes to the cookies.
+ return True
+ else:
+ return False
+ else:
+ return False
+
+Using it in a request might look like::
+
+ import tornado.web
+ from Mojo.RequestHandlers.MojoHandler import MojoRequestHandler
+ from Mojo.Auth.Mixins.MojoAuthMixin import MojoAuthMixin
+ from Mojo.Auth.models import User
+ from Mojo.Auth.Helpers import login_assistant
+
+ #To implement the mixin, simply subclass it alongside the regular MojoRequestHandler and the authentication
+ #funcitonality will be come available.
+
+ class loginHandler(MojoRequestHandler, MojoAuthMixin):
+
+ def get(self):
+ #Override the get function to render the page, check current_user to see if we're already logged in
+ if self.current_user:
+ self.render('login.html', error='ALREADY LOGGED IN')
+ else:
+ self.render('login.html', error=None)
+
+ def post(self):
+ #Get the username and password from the request
+ username = self.get_argument('username')
+ password = self.get_argument('password')
+
+ target = self.get_argument('next', '/admin/')
+
+ #Get the user from the database
+ thisUser = User.find_one({'username':username})
+
+ #Log the user in using the login assistant
+ if login_assistant(thisUser, password, self):
+ self.redirect(target)
+ else:
+ self.render('login.html', error='Login failed')
+
+The SessionMixin
+----------------
+
+The SessionMixin comes in two flavours: Syncronous and Asyncronous, depending on what backend is being used in Mojo.
+To implement the SessionMixin, simply add it to the inheritance list as part of your RequestManager::
+
+ from Mojo.Auth.Mixins.SessionMixins import SessionMixin_Sync
+ class loginHandler(MojoRequestHandler, SessionMixin_Sync):
+
+ def get(self):
+ pass
+
+The SessionMixin exposes some basic functionality that will let you get and set session data as part of your site and save
+it to the database.
+
+All session data is stored in the SessionModel as a Base64 encoded string that is a ``dict``. To get and set session
+values is quite straightforward::
+
+ from Mojo.Auth.Mixins.SessionMixins import SessionMixin_Sync
+ class loginHandler(MojoRequestHandler, SessionMixin_Sync):
+
+ def get(self):
+ self.set_session_key('keyname', 'value')
+
+ value = self.get_session_key('keyname')
+
+ self.render('template.html', session_key_value = value)
View
168 Documentation/_build/html/_sources/docs/models.txt
@@ -1,3 +1,167 @@
-Using the ORM and Models in your apps
-=====================================
+The Mojo ORM and Models
+=======================
+To make working with databases easier, and to ensure a consistent set of tools when saving and moving data, Mojo
+uses models to define validation and data structures, and then uses these to set up how data will look in the database.
+
+Currently, Mojo only supports MongoDB, but we are hoping to add support for Redis and CouchDB soon. We actively encourage
+contributors, so anyone feeling the urge to help us write a new backend for their favourite datastore can drop us a line
+in our Google Group.
+
+What are Models?
+----------------
+
+For anyone familiar with Django, Mojo Models will seem very similar, and take heavy influence from the framework. Models
+are a way for you to organise and structure your data as python objects so you can transparently use them (without a
+data store) in your application.
+
+Models are very simple - they are a defined class, with a series of fields that you can use to represent your data and the
+various validation methods you would like run against those fields before the object is written to the database.
+
+Why Models?
+-----------
+
+Because our first database to support was MongoDB, it became apparent that what was really missing was a good way to
+enforce structure and a certain degree of validation on stored data. Being Schema-less, it becomes very easy to not
+validate stored input due to the extra burden of writing the validation code, as well as not manging schema evolutions
+as schemas change over the lifecycle of your project.
+
+Models make this process easiewr by pre-defining data types, relations and object properties prior to saving, while exposing
+all the benefits of having a neat python object to represent your data set without resporting to direct database access.
+
+Do I have to use Models?
+------------------------
+
+Not at all, you can completely ignore the ORM and model structure in your project and directly access your database using your
+favourite driver.
+
+Using Models
+============
+
+To implement a model for your app, simply define it in the ``models.py`` file in your app directory::
+
+ from Mojo.ObjectMapper.ModelPrototype import Model
+ from Mojo.ObjectMapper.Fields import *
+ import datetime
+
+ #This is a non-database class, not stored in the DB but embedded in the BlogPost class below
+ #the key difference is the lack of an _id field
+ class Tag(Model):
+ tag_name = StringField()
+
+ #a simple model to hold blog posts
+ class BlogPost(Model):
+ _id = ObjectIDField()
+ title = StringField(allow_empty=False)
+ slug = StringField(allow_empty=False)
+ post_intro = StringField()
+ post_body = StringField()
+ date_published = DateTimeField(default=datetime.datetime.now())
+ tags = ListField(of=Tag)
+ visible = BooleanField(default=True)
+
+In the above example we've defined two models, the first ``Tag`` model is a straightforward class that is **not** a database object
+the key distinction here is the lack of the ``_id`` field (this is only relevant to the MongoDB backend as it requires an ID to be
+explicitly defined).
+
+The second model ``BlogPost`` is the real model, and lists a series of fields to represent data types, fields can be anything, so
+long as they subclass the ``Mojo.ObjectMapper.FieldPrototype.Field`` object.
+
+Accessing model data
+^^^^^^^^^^^^^^^^^^^^
+
+You can access the above model quite easily in your code::
+
+ new_minimal_post = BlogPost({
+ 'title':u'a new post',
+ 'slug' : 'newpost'
+ })
+
+ #access some properties
+ print new_minimal_post.title
+ > a new post
+
+ #save it (assuming synchronous DB backend):
+ thispost = new_minimal_post.save()
+
+ print thispost._id
+ > 50571e5f3d941cdc4487bdf1
+
+Models can be assigned data in dictionary format as part of their initialisation, or empty and then using dot-notation
+for each of their properties. So, in the example above, the following would work just as well::
+
+ new_minimal_post = BlogPost()
+ new_minimal_post.title = u'a new post'
+ new_minimal_post.slug = 'newpost'
+
+ #access some properties
+ print new_minimal_post.title
+ > a new post
+
+ #save it (assuming synchronous DB backend):
+ thispost = new_minimal_post.save()
+
+ print thispost._id
+ > 50571e5f3d941cdc4487bdf1
+
+``Model`` objects are dictionaries, so if you print out or access them in any way, they should behave in the same way as a
+stamdard python ``dict`` object.
+
+Saving, Updating, Finding and Deleting
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Saving is very straightforward in mojo, and as can be seen from the example above, can easily be accomplished with the ``save()``
+instance method.
+
+The main read/write operations of a model are as follows:
+
+- ``save()``: Called on an instance of the model, this will attempt to save the data to the database, if the object has an initialised ``_id`` value then it will be updated, otherwise it will perform an insert
+- ``delete()``: Called on an instance of the model, thjis will delete it from the database
+- ``find()``: Called on the Model object (class method), will use the criteria passed to find to return a list of instantiated model instances
+- ``find_one()``: Called on the model object (class method), will use the criteria passed to find a single model object
+- ``delete_bulk([list])``: Pass a list of objects ot this function for a bulk delete operation
+
+Both the ``find()`` and ``find_one()`` operations take MongoDB style ``dict`` objects as request parameters and follow the pymongo style of queries.
+
+Asynchronous operations
+^^^^^^^^^^^^^^^^^^^^^^^
+
+One of the most appealing aspects of Tornado is it's ability to work asynchronously, and Mojo takes that to heart, ensuring taht you can just as well
+use the asynchronous style of development with the ORM and Models.
+
+To use the Asynchronous driver, make sure that you have changed it in your ``settings.py`` file::
+
+ DATABASE = {
+ 'backend': 'Mojo.Backends.AsyncmongoBackend.asyncmongo_backend',
+ 'name': 'YOUR_DB_NAME',
+ 'host': '127.0.0.1',
+ 'port': 27017
+ }
+
+To start using it in your code, all models make an ``_async`` version of all operations available, that can be used with
+traditional callback-style async handling or Tornado's ``gen`` module style (for more readable code)::
+
+ class myRequestHandler(MojoRequestHandler):
+ @gen.engine
+ @tornado.web.asynchronous
+ def get(self):
+ from bson.objectid import ObjectId
+ thisPost = yield gen.Task(BlogPost.find_one_async, {'_id':ObjectId('5059fb6b3d941cdc4487bdff')})
+
+ self.render('template.html', post=thisPost)
+
+If you want to use callback-style development::
+
+ class myRequestHandler(MojoRequestHandler):
+
+ def callback(value):
+ self.render('template.html', post=value)
+
+ @gen.engine
+ @tornado.web.asynchronous
+ def get(self):
+ from bson.objectid import ObjectId
+ yield gen.Task(BlogPost.find_one_async, {'_id':ObjectId('5059fb6b3d941cdc4487bdff')}, callback=self.callback)
+
+**NOTE:** The ORM and Models modules are still in very early stage development, please report any bugs to the developer on the
+source-control page on BitBucket.
View
9 Documentation/_build/html/_sources/docs/quickstart.txt
@@ -1,7 +1,7 @@
Quickstart: Using Mojo for the first time
=========================================
-This is a quickstart tutorial that will get you set up and running with Mojo for the first time.
+This is a quick-start tutorial that will get you set up and running with Mojo for the first time.
Installation
------------
@@ -12,10 +12,11 @@ Installation
4. From the command line in the new folder run ``python setup.py install``
This should install Mojo into your python path. However, there is one more step that you may need to do to fully
-take advantage of Mojo's helper apps, and that is to make mojo_manager available in your PATH, for linux and Mac OSX users,
+take advantage of Mojo's helper apps, and that is to make ``mojo_manager`` available in your ``PATH``, for linux and Mac OSX users,
this can be accomplished by doing something like::
ln /usr/bin/python2.7/Lib/site-packages/Mojo/mojo_manager.py /usr/sbin/mojo_manager.py
+ chmod +x /usr/sbin/mojo_manager.py
On windows, adding the Mojo site-packages directory should be enough to give gloabl access to ``mojo_manager``
@@ -23,6 +24,8 @@ Once you've done that, you should be able to test your installation by opeining
import Mojo
+If there are no import errors then you shoulod be ready to get started.
+
*Note:* It is recommended to deploy Mojo in something like virtualenv to ensure you can easily keep it (and your app)
up to date without affecting your main Python setup and other projects.
@@ -83,7 +86,7 @@ and make sure the ``INSTALLED_APPS`` section looks like this::
Once you've made the change, simply save the file and open up your terminal window in the directory where ``runserver.py`` is located, then
type the following::
- ``python runserver.py``
+ python runserver.py
You should see::
View
73 Documentation/_build/html/_sources/docs/socketio.txt
@@ -1,3 +1,72 @@
-Real Mojo: SocketIO
-===================
+Mojo and SocketIO
+=================
+One of the strengths of Tornado is it's ability to handle asynchronous requests and support for websockets. Top make Mojo
+more of a responsive framework, we've decided to bundle ``TornadIO2`` functionality as part of the overall package.
+
+For those that do not know what ``TornadIO2`` is, it is a ``SocketIO`` server implementation written in Python for Tornado, and
+makes it transparent to implement SocketIO clients into your app.
+
+By default, Mojo will start a ``TornadIO`` server for you that multiplexes a channel connection for each of the apps in your
+project.
+
+So if you have 2 apps: ``App1`` and ``App2``, then you will be able to speak to either of these apps via SocketIO on the
+client by connecting to the ``/App1Socket`` or ``/App2Socket`` channels in your client side configuration.
+
+To configure what commands the server should intitiate on connection, send event or receive event, simply edit the ``socket_handlers.py``
+file in your app folder::
+
+ from Mojo.SocketHandlers.BaseSocketHandler import MojoSocketHandler, CURRENT_SESSIONS, LOGGED_IN_SESSIONS
+
+ #Setup your socket connections here
+ class SocketConnectionHandler(MojoSocketHandler):
+
+ def on_message(self, msg):
+ #Do something cool when a message arrives
+ pass
+
+To make the most of ``TornadIO2`` and ``SocketIO`` we'd recommend you read the documentation for both as their inner workings fall outside
+of the remit of the Mojo documentation.
+
+Helpful Tracking
+----------------
+
+Mojo does some handy tracking for you if you use the ``MojoSocketHandler`` to manage your socket connections. Mojo will
+automatically register all connections in two variables that enable you to communicate with users directly from the start,
+these variables are ``CURRENT_SESSIONS`` and ``LOGGED_IN_SESSIONS``
+
+``CURRENT_SESSIONS``
+^^^^^^^^^^^^^^^^^^^^
+
+This is a dictionary object that will track each connection by their Session ID. The session ID is a secure Tornado cookie
+that is called ``session_id``, if you are using the ``MojoSessionMixin`` module, this will be set for you, however if you
+want to roll your own session management, you can just set this cookie and the user will be tracked by the ID in the ``SocketHandler``.
+
+This will enable you to do something like::
+
+ from Mojo.RequestHandlers.MojoHandler import MojoRequestHandler
+ from Mojo.SocketHandlers.BaseSocketHandler import CURRENT_SESSIONS
+ import json
+
+ class HelloWorldHandler(MojoRequestHandler):
+ def get(self, *args, **kwargs):
+
+ jsonObj = json.dumps({'data':'%s has joined the chat' % (self.session_id)})
+
+ for session in CURRENT_SESSIONS:
+ session.emit('joinedStatus', jsonObj)
+
+ self.render('hello.html')
+
+Although the above code is not functional, the principle is valid - in this example, you could use the CURRENT_SESSIONS object
+to broadcast to all active users that a new user has joined the conversation.
+
+``LOGGED_IN_SESSIONS``
+^^^^^^^^^^^^^^^^^^^^^^
+
+If you are using the AuthMixin from Mojo, then it will set an encrypted cookie of the name ``logged_in`` with the user ID
+of the current user. Naturally, you can set this yourself to whatever identifier you like if you decide not use the mixins.
+
+Any session that is identified as Logged in will be added to the ``LOGGED_IN_SESSIONS`` dictionary, and will enable you to
+interact with users. In a similar vein to the ``CURRENT_SESSIONS`` object, you would now be able to send specific messages only
+to logged in members of your app.
View
15 Documentation/_build/html/_sources/docs/urls.txt
@@ -1,3 +1,18 @@
Routing pages with URL's
========================
+Mojo moves the URL definition of your app to the file ``urls.py``, this file contains a list object called ``url_patterns``
+that contains tuples mapping a URL to a ``RequestHandler`` in your ``views.py``.
+
+All entries work the same way as they do with standard Tornado mappings, when your server starts up, Mojo will automatically
+concatenate all the URL's for you into a single pattern set to ensure that all your apps are available in the project
+without mixing functionality across apps::
+
+ from views import myRequestHandler
+
+ urlpatterns = [
+ ('/hello', myRequestHandler),
+ ]
+
+All URL patterns can be regex groups - see the Tornado documentation for more details on how to use the URL routing
+in a Tornado app.
View
65 Documentation/_build/html/_sources/docs/views.txt
@@ -0,0 +1,65 @@
+Mojo Views
+==========
+
+Mojo views are where you will write most of your application and page handling logic. In the ``views.py`` file, you will
+sub-clas the MojoRequestHandler class to create your application.
+
+The MojoRequestHandler is a slightly modified version of the basic Tornado RequestHandler that makes the local templates available to
+the interpreter and adds support for prettier error formatting, it is also required to make the ``SessionMixin`` and ``AuthMixin``
+classes to work as they depend on the ``MojoRequestHandler`` base class.
+
+*Note:* It completely possible to develop with Mojo using standard ``equestHandlers``, simply subclass them as you would normally
+and use them in your ``urls.py``
+
+Views Quick-start:
+------------------
+
+To write your first view, subclas the MojoRequestHandler class, type thi into your view handler::
+
+ from Mojo.RequestHandlers.MojoHandler import MojoRequestHandler
+
+ class HelloWorldHandler(MojoRequestHandler):
+ def get(self, *args, **kwargs):
+ self.render('hello.html')
+
+And then mak sure it is accessible in your ``urls.py`` file::
+
+ from views import *
+
+ urlpatterns = [
+ #Place your URL Routes / RequestHandler mappings in here for this app, e.g.
+ ('/', HelloWorldHandler),
+ ]
+
+You will also need to actually create the template file, ``hello.html``, it could lok somwthing like this::
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+ <html>
+ <head>
+ <title>Hello from Mojo!</title>
+ </head>
+ <body>
+ <h1>Hi there, I'm a template inside Mojo!</h1>
+ <p>This is a tempalte file that is stored in your apps template directory.</p>
+ </body>
+ </html>
+
+Save this file to your app ``templates`` directory and make sure that your app is listed in the ``settings.py`` ``INSTALLED_APPS``
+ setting::
+
+ INSTALLED_APPS = [
+ 'HelloWorldApp',
+ ]
+
+Now you just need to run your server, in a command line window, in your project directory type::
+
+ python runserver.py
+
+If your server is already running, and you have ``DEBUG=True`` set in your ``settings.py`` file, it should automatically restart when you save
+the above changes.
+
+When you navigate to ``http://localhost:8000/`` you should see your template being rendered out...
+
+The MojoRequestHandler behaves the same way as the Tornado request handler, we recommend the reader check the Tornado documentation
+to get fully up to speed with what the capabilities are of ``RequestHandler`` objects.
View
2  Documentation/_build/html/_sources/index.txt
@@ -32,9 +32,9 @@ Contents:
docs/quickstart.rst
docs/apps.rst
+ docs/views.rst
docs/urls.rst
docs/models.rst
- docs/backends.rst
docs/socketio.rst
docs/authentication.rst
View
8 Documentation/_build/html/docs/api/Auth.html
@@ -27,7 +27,7 @@
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../../index.html" />
<link rel="next" title="Mojo.Auth.Mixins" href="Mixins.html" />
- <link rel="prev" title="Using Mojo’s Auth module" href="../authentication.html" />
+ <link rel="prev" title="Using Mojo’s Auth and Session Mixins" href="../authentication.html" />
</head>
<body>
<div class="related">
@@ -43,7 +43,7 @@
<a href="Mixins.html" title="Mojo.Auth.Mixins"
accesskey="N">next</a> |</li>
<li class="right" >
- <a href="../authentication.html" title="Using Mojo’s Auth module"
+ <a href="../authentication.html" title="Using Mojo’s Auth and Session Mixins"
accesskey="P">previous</a> |</li>
<li><a href="../../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
@@ -398,7 +398,7 @@
<h4>Previous topic</h4>
<p class="topless"><a href="../authentication.html"
- title="previous chapter">Using Mojo&#8217;s Auth module</a></p>
+ title="previous chapter">Using Mojo&#8217;s Auth and Session Mixins</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Mixins.html"
title="next chapter">Mojo.Auth.Mixins</a></p>
@@ -437,7 +437,7 @@
<a href="Mixins.html" title="Mojo.Auth.Mixins"
>next</a> |</li>
<li class="right" >
- <a href="../authentication.html" title="Using Mojo’s Auth module"
+ <a href="../authentication.html" title="Using Mojo’s Auth and Session Mixins"
>previous</a> |</li>
<li><a href="../../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
View
32 Documentation/_build/html/docs/apps.html
@@ -8,7 +8,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>What are apps &mdash; Mojo 0.1 documentation</title>
+ <title>Mojo Apps &mdash; Mojo 0.1 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
@@ -26,7 +26,7 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="next" title="Routing pages with URL’s" href="urls.html" />
+ <link rel="next" title="Mojo Views" href="views.html" />
<link rel="prev" title="Quickstart: Using Mojo for the first time" href="quickstart.html" />
</head>
<body>
@@ -40,7 +40,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="urls.html" title="Routing pages with URL’s"
+ <a href="views.html" title="Mojo Views"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="quickstart.html" title="Quickstart: Using Mojo for the first time"
@@ -54,8 +54,24 @@
<div class="bodywrapper">
<div class="body">
- <div class="section" id="what-are-apps">
-<h1>What are apps<a class="headerlink" href="#what-are-apps" title="Permalink to this headline">¶</a></h1>
+ <div class="section" id="mojo-apps">
+<h1>Mojo Apps<a class="headerlink" href="#mojo-apps" title="Permalink to this headline">¶</a></h1>
+<p>When developing with Mojo, it&#8217;s more elegant to modularise functionality into Apps, and this is the default behaviour
+of the Mojo server loader.</p>
+<p>Apps serve as a collection of RequestHandlers, URL Mappings, Models and Templates that make up a set of functionality
+in your project.</p>
+<p>To get started with an app in your project, you can use the <tt class="docutils literal"><span class="pre">mojo_manager.py</span></tt> helper application that will auto create
+your project folder for you:</p>
+<div class="highlight-python"><pre>python mojo_manager.py -a [YOUR_APP_NAME]</pre>
+</div>
+<p>This will create an app folder with certain key files:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">models.py</span></tt>: This is where you define your models which can be used with your database and forms</li>
+<li><tt class="docutils literal"><span class="pre">socket_handlers.py</span></tt>: This is where you define your SocketIO behaviour, each app has it&#8217;s own dedicated (multiplexed) channel under <tt class="docutils literal"><span class="pre">/[appname]Socket</span></tt> to separate out functionality</li>
+<li><tt class="docutils literal"><span class="pre">ui_modules.py</span></tt>: The ui_modules you might or mihjgt not be using</li>
+<li><tt class="docutils literal"><span class="pre">urls.py</span></tt>: The URL mappings for your request handlers</li>
+<li><tt class="docutils literal"><span class="pre">views.py</span></tt>: A list of your <tt class="docutils literal"><span class="pre">RequestHandler</span></tt> classes that handle your app functionality</li>
+</ul>
</div>
@@ -68,8 +84,8 @@
<p class="topless"><a href="quickstart.html"
title="previous chapter">Quickstart: Using Mojo for the first time</a></p>
<h4>Next topic</h4>
- <p class="topless"><a href="urls.html"
- title="next chapter">Routing pages with URL&#8217;s</a></p>
+ <p class="topless"><a href="views.html"
+ title="next chapter">Mojo Views</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/apps.txt"
@@ -102,7 +118,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="urls.html" title="Routing pages with URL’s"
+ <a href="views.html" title="Mojo Views"
>next</a> |</li>
<li class="right" >
<a href="quickstart.html" title="Quickstart: Using Mojo for the first time"
View
115 Documentation/_build/html/docs/authentication.html
@@ -8,7 +8,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Using Mojo’s Auth module &mdash; Mojo 0.1 documentation</title>
+ <title>Using Mojo’s Auth and Session Mixins &mdash; Mojo 0.1 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
@@ -26,7 +26,8 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="prev" title="Real Mojo: SocketIO" href="socketio.html" />
+ <link rel="next" title="Mojo.Auth" href="api/Auth.html" />
+ <link rel="prev" title="Mojo and SocketIO" href="socketio.html" />
</head>
<body>
<div class="related">
@@ -39,7 +40,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="socketio.html" title="Real Mojo: SocketIO"
+ <a href="api/Auth.html" title="Mojo.Auth"
+ accesskey="N">next</a> |</li>
+ <li class="right" >
+ <a href="socketio.html" title="Mojo and SocketIO"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
@@ -50,8 +54,90 @@
<div class="bodywrapper">
<div class="body">
- <div class="section" id="using-mojo-s-auth-module">
-<h1>Using Mojo&#8217;s Auth module<a class="headerlink" href="#using-mojo-s-auth-module" title="Permalink to this headline">¶</a></h1>
+ <div class="section" id="using-mojo-s-auth-and-session-mixins">
+<h1>Using Mojo&#8217;s Auth and Session Mixins<a class="headerlink" href="#using-mojo-s-auth-and-session-mixins" title="Permalink to this headline">¶</a></h1>
+<p>To make Tornado a bit easier to use and integrate with your application, Mojo provides a sesison management mixin that
+adds database-backed sessions to your requests.</p>
+<p>The Session Mixin assumes that a database backend and ORM is present, which is why it comes in both sync and async flavors.
+The AuthMixin does not assume that a database is present and solely uses the set_cookie functionality of Tornado to make
+the get_current_user functionality work.</p>
+<div class="section" id="authmixin">
+<h2>AuthMixin<a class="headerlink" href="#authmixin" title="Permalink to this headline">¶</a></h2>
+<p>The AuthMixin basically overrides get_current_user() in the MojoRequestHandler and adds a SessionManager object to the
+attributes of the RequestHandler. Using the SessionManager, it is possible to login/logout the user:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="n">thisUser</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
+ <span class="k">if</span> <span class="n">is_authenticated</span><span class="p">:</span>
+ <span class="n">SessionManager</span><span class="p">(</span><span class="n">request</span><span class="p">)</span><span class="o">.</span><span class="n">_login</span><span class="p">(</span><span class="n">thisUser</span><span class="p">)</span> <span class="c">#Will make the relevant changes to the cookies.</span>
+ <span class="k">return</span> <span class="bp">True</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="k">return</span> <span class="bp">False</span>
+<span class="k">else</span><span class="p">:</span>
+ <span class="k">return</span> <span class="bp">False</span>
+</pre></div>
+</div>
+<p>Using it in a request might look like:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">tornado.web</span>
+<span class="kn">from</span> <span class="nn">Mojo.RequestHandlers.MojoHandler</span> <span class="kn">import</span> <span class="n">MojoRequestHandler</span>
+<span class="kn">from</span> <span class="nn">Mojo.Auth.Mixins.MojoAuthMixin</span> <span class="kn">import</span> <span class="n">MojoAuthMixin</span>
+<span class="kn">from</span> <span class="nn">Mojo.Auth.models</span> <span class="kn">import</span> <span class="n">User</span>
+<span class="kn">from</span> <span class="nn">Mojo.Auth.Helpers</span> <span class="kn">import</span> <span class="n">login_assistant</span>
+
+<span class="c">#To implement the mixin, simply subclass it alongside the regular MojoRequestHandler and the authentication</span>
+<span class="c">#funcitonality will be come available.</span>
+
+<span class="k">class</span> <span class="nc">loginHandler</span><span class="p">(</span><span class="n">MojoRequestHandler</span><span class="p">,</span> <span class="n">MojoAuthMixin</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="c">#Override the get function to render the page, check current_user to see if we&#39;re already logged in</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_user</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;login.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="s">&#39;ALREADY LOGGED IN&#39;</span><span class="p">)</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;login.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
+
+ <span class="k">def</span> <span class="nf">post</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="c">#Get the username and password from the request</span>
+ <span class="n">username</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_argument</span><span class="p">(</span><span class="s">&#39;username&#39;</span><span class="p">)</span>
+ <span class="n">password</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_argument</span><span class="p">(</span><span class="s">&#39;password&#39;</span><span class="p">)</span>
+
+ <span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_argument</span><span class="p">(</span><span class="s">&#39;next&#39;</span><span class="p">,</span> <span class="s">&#39;/admin/&#39;</span><span class="p">)</span>
+
+ <span class="c">#Get the user from the database</span>
+ <span class="n">thisUser</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">find_one</span><span class="p">({</span><span class="s">&#39;username&#39;</span><span class="p">:</span><span class="n">username</span><span class="p">})</span>
+
+ <span class="c">#Log the user in using the login assistant</span>
+ <span class="k">if</span> <span class="n">login_assistant</span><span class="p">(</span><span class="n">thisUser</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="bp">self</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">redirect</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;login.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="s">&#39;Login failed&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="the-sessionmixin">
+<h2>The SessionMixin<a class="headerlink" href="#the-sessionmixin" title="Permalink to this headline">¶</a></h2>
+<p>The SessionMixin comes in two flavours: Syncronous and Asyncronous, depending on what backend is being used in Mojo.
+To implement the SessionMixin, simply add it to the inheritance list as part of your RequestManager:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">Mojo.Auth.Mixins.SessionMixins</span> <span class="kn">import</span> <span class="n">SessionMixin_Sync</span>
+<span class="k">class</span> <span class="nc">loginHandler</span><span class="p">(</span><span class="n">MojoRequestHandler</span><span class="p">,</span> <span class="n">SessionMixin_Sync</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="k">pass</span>
+</pre></div>
+</div>
+<p>The SessionMixin exposes some basic functionality that will let you get and set session data as part of your site and save
+it to the database.</p>
+<p>All session data is stored in the SessionModel as a Base64 encoded string that is a <tt class="docutils literal"><span class="pre">dict</span></tt>. To get and set session
+values is quite straightforward:</p>
+<div class="highlight-python"><pre>from Mojo.Auth.Mixins.SessionMixins import SessionMixin_Sync
+ class loginHandler(MojoRequestHandler, SessionMixin_Sync):
+
+ def get(self):
+ self.set_session_key('keyname', 'value')
+
+ value = self.get_session_key('keyname')
+
+ self.render('template.html', session_key_value = value)</pre>
+</div>
+</div>
</div>
@@ -60,9 +146,21 @@
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
+ <h3><a href="../index.html">Table Of Contents</a></h3>
+ <ul>
+<li><a class="reference internal" href="#">Using Mojo&#8217;s Auth and Session Mixins</a><ul>
+<li><a class="reference internal" href="#authmixin">AuthMixin</a></li>
+<li><a class="reference internal" href="#the-sessionmixin">The SessionMixin</a></li>
+</ul>
+</li>
+</ul>
+
<h4>Previous topic</h4>
<p class="topless"><a href="socketio.html"
- title="previous chapter">Real Mojo: SocketIO</a></p>
+ title="previous chapter">Mojo and SocketIO</a></p>
+ <h4>Next topic</h4>
+ <p class="topless"><a href="api/Auth.html"
+ title="next chapter">Mojo.Auth</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/authentication.txt"
@@ -95,7 +193,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="socketio.html" title="Real Mojo: SocketIO"
+ <a href="api/Auth.html" title="Mojo.Auth"
+ >next</a> |</li>
+ <li class="right" >
+ <a href="socketio.html" title="Mojo and SocketIO"
>previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
View
167 Documentation/_build/html/docs/models.html
@@ -8,7 +8,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Using the ORM and Models in your apps &mdash; Mojo 0.1 documentation</title>
+ <title>The Mojo ORM and Models &mdash; Mojo 0.1 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
@@ -26,7 +26,7 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="next" title="Using the Mojo backends" href="backends.html" />
+ <link rel="next" title="Mojo and SocketIO" href="socketio.html" />
<link rel="prev" title="Routing pages with URL’s" href="urls.html" />
</head>
<body>
@@ -40,7 +40,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="backends.html" title="Using the Mojo backends"
+ <a href="socketio.html" title="Mojo and SocketIO"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="urls.html" title="Routing pages with URL’s"
@@ -54,8 +54,148 @@
<div class="bodywrapper">
<div class="body">
- <div class="section" id="using-the-orm-and-models-in-your-apps">
-<h1>Using the ORM and Models in your apps<a class="headerlink" href="#using-the-orm-and-models-in-your-apps" title="Permalink to this headline">¶</a></h1>
+ <div class="section" id="the-mojo-orm-and-models">
+<h1>The Mojo ORM and Models<a class="headerlink" href="#the-mojo-orm-and-models" title="Permalink to this headline">¶</a></h1>
+<p>To make working with databases easier, and to ensure a consistent set of tools when saving and moving data, Mojo
+uses models to define validation and data structures, and then uses these to set up how data will look in the database.</p>
+<p>Currently, Mojo only supports MongoDB, but we are hoping to add support for Redis and CouchDB soon. We actively encourage
+contributors, so anyone feeling the urge to help us write a new backend for their favourite datastore can drop us a line
+in our Google Group.</p>
+<div class="section" id="what-are-models">
+<h2>What are Models?<a class="headerlink" href="#what-are-models" title="Permalink to this headline">¶</a></h2>
+<p>For anyone familiar with Django, Mojo Models will seem very similar, and take heavy influence from the framework. Models
+are a way for you to organise and structure your data as python objects so you can transparently use them (without a
+data store) in your application.</p>
+<p>Models are very simple - they are a defined class, with a series of fields that you can use to represent your data and the
+various validation methods you would like run against those fields before the object is written to the database.</p>
+</div>
+<div class="section" id="why-models">
+<h2>Why Models?<a class="headerlink" href="#why-models" title="Permalink to this headline">¶</a></h2>
+<p>Because our first database to support was MongoDB, it became apparent that what was really missing was a good way to
+enforce structure and a certain degree of validation on stored data. Being Schema-less, it becomes very easy to not
+validate stored input due to the extra burden of writing the validation code, as well as not manging schema evolutions
+as schemas change over the lifecycle of your project.</p>
+<p>Models make this process easiewr by pre-defining data types, relations and object properties prior to saving, while exposing
+all the benefits of having a neat python object to represent your data set without resporting to direct database access.</p>
+</div>
+<div class="section" id="do-i-have-to-use-models">
+<h2>Do I have to use Models?<a class="headerlink" href="#do-i-have-to-use-models" title="Permalink to this headline">¶</a></h2>
+<p>Not at all, you can completely ignore the ORM and model structure in your project and directly access your database using your
+favourite driver.</p>
+</div>
+</div>
+<div class="section" id="using-models">
+<h1>Using Models<a class="headerlink" href="#using-models" title="Permalink to this headline">¶</a></h1>
+<p>To implement a model for your app, simply define it in the <tt class="docutils literal"><span class="pre">models.py</span></tt> file in your app directory:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">Mojo.ObjectMapper.ModelPrototype</span> <span class="kn">import</span> <span class="n">Model</span>
+<span class="kn">from</span> <span class="nn">Mojo.ObjectMapper.Fields</span> <span class="kn">import</span> <span class="o">*</span>
+<span class="kn">import</span> <span class="nn">datetime</span>
+
+<span class="c">#This is a non-database class, not stored in the DB but embedded in the BlogPost class below</span>
+<span class="c">#the key difference is the lack of an _id field</span>
+<span class="k">class</span> <span class="nc">Tag</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
+ <span class="n">tag_name</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">()</span>
+
+<span class="c">#a simple model to hold blog posts</span>
+<span class="k">class</span> <span class="nc">BlogPost</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
+ <span class="n">_id</span> <span class="o">=</span> <span class="n">ObjectIDField</span><span class="p">()</span>
+ <span class="n">title</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">(</span><span class="n">allow_empty</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
+ <span class="n">slug</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">(</span><span class="n">allow_empty</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
+ <span class="n">post_intro</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">()</span>
+ <span class="n">post_body</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">()</span>
+ <span class="n">date_published</span> <span class="o">=</span> <span class="n">DateTimeField</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
+ <span class="n">tags</span> <span class="o">=</span> <span class="n">ListField</span><span class="p">(</span><span class="n">of</span><span class="o">=</span><span class="n">Tag</span><span class="p">)</span>
+ <span class="n">visible</span> <span class="o">=</span> <span class="n">BooleanField</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>In the above example we&#8217;ve defined two models, the first <tt class="docutils literal"><span class="pre">Tag</span></tt> model is a straightforward class that is <strong>not</strong> a database object
+the key distinction here is the lack of the <tt class="docutils literal"><span class="pre">_id</span></tt> field (this is only relevant to the MongoDB backend as it requires an ID to be
+explicitly defined).</p>
+<p>The second model <tt class="docutils literal"><span class="pre">BlogPost</span></tt> is the real model, and lists a series of fields to represent data types, fields can be anything, so
+long as they subclass the <tt class="docutils literal"><span class="pre">Mojo.ObjectMapper.FieldPrototype.Field</span></tt> object.</p>
+<p>You can access the above model quite easily in your code:</p>
+<div class="highlight-python"><pre>new_minimal_post = BlogPost({
+ 'title':u'a new post',
+ 'slug' : 'newpost'
+})
+
+#access some properties
+print new_minimal_post.title
+&gt; a new post
+
+#save it (assuming synchronous DB backend):
+thispost = new_minimal_post.save()
+
+print thispost._id
+&gt; 50571e5f3d941cdc4487bdf1</pre>
+</div>
+<p>Models can be assigned data in dictionary format as part of their initialisation, or empty and then using dot-notation
+for each of their properties. So, in the example above, the following would work just as well:</p>
+<div class="highlight-python"><pre>new_minimal_post = BlogPost()
+new_minimal_post.title = u'a new post'
+new_minimal_post.slug = 'newpost'
+
+#access some properties
+print new_minimal_post.title
+&gt; a new post
+
+#save it (assuming synchronous DB backend):
+thispost = new_minimal_post.save()
+
+print thispost._id
+&gt; 50571e5f3d941cdc4487bdf1</pre>
+</div>
+<p><tt class="docutils literal"><span class="pre">Model</span></tt> objects are dictionaries, so if you print out or access them in any way, they should behave in the same way as a
+stamdard python <tt class="docutils literal"><span class="pre">dict</span></tt> object.</p>
+<p>Saving is very straightforward in mojo, and as can be seen from the example above, can easily be accomplished with the <tt class="docutils literal"><span class="pre">save()</span></tt>
+instance method.</p>
+<p>The main read/write operations of a model are as follows:</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">save()</span></tt>: Called on an instance of the model, this will attempt to save the data to the database, if the object has an initialised <tt class="docutils literal"><span class="pre">_id</span></tt> value then it will be updated, otherwise it will perform an insert</li>
+<li><tt class="docutils literal"><span class="pre">delete()</span></tt>: Called on an instance of the model, thjis will delete it from the database</li>
+<li><tt class="docutils literal"><span class="pre">find()</span></tt>: Called on the Model object (class method), will use the criteria passed to find to return a list of instantiated model instances</li>
+<li><tt class="docutils literal"><span class="pre">find_one()</span></tt>: Called on the model object (class method), will use the criteria passed to find a single model object</li>
+<li><tt class="docutils literal"><span class="pre">delete_bulk([list])</span></tt>: Pass a list of objects ot this function for a bulk delete operation</li>
+</ul>
+<p>Both the <tt class="docutils literal"><span class="pre">find()</span></tt> and <tt class="docutils literal"><span class="pre">find_one()</span></tt> operations take MongoDB style <tt class="docutils literal"><span class="pre">dict</span></tt> objects as request parameters and follow the pymongo style of queries.</p>
+<p>One of the most appealing aspects of Tornado is it&#8217;s ability to work asynchronously, and Mojo takes that to heart, ensuring taht you can just as well
+use the asynchronous style of development with the ORM and Models.</p>
+<p>To use the Asynchronous driver, make sure that you have changed it in your <tt class="docutils literal"><span class="pre">settings.py</span></tt> file:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">DATABASE</span> <span class="o">=</span> <span class="p">{</span>
+ <span class="s">&#39;backend&#39;</span><span class="p">:</span> <span class="s">&#39;Mojo.Backends.AsyncmongoBackend.asyncmongo_backend&#39;</span><span class="p">,</span>
+ <span class="s">&#39;name&#39;</span><span class="p">:</span> <span class="s">&#39;YOUR_DB_NAME&#39;</span><span class="p">,</span>
+ <span class="s">&#39;host&#39;</span><span class="p">:</span> <span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span>
+ <span class="s">&#39;port&#39;</span><span class="p">:</span> <span class="mi">27017</span>
+<span class="p">}</span>
+</pre></div>
+</div>
+<p>To start using it in your code, all models make an <tt class="docutils literal"><span class="pre">_async</span></tt> version of all operations available, that can be used with
+traditional callback-style async handling or Tornado&#8217;s <tt class="docutils literal"><span class="pre">gen</span></tt> module style (for more readable code):</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">myRequestHandler</span><span class="p">(</span><span class="n">MojoRequestHandler</span><span class="p">):</span>
+ <span class="nd">@gen.engine</span>
+ <span class="nd">@tornado.web.asynchronous</span>
+ <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="kn">from</span> <span class="nn">bson.objectid</span> <span class="kn">import</span> <span class="n">ObjectId</span>
+ <span class="n">thisPost</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">gen</span><span class="o">.</span><span class="n">Task</span><span class="p">(</span><span class="n">BlogPost</span><span class="o">.</span><span class="n">find_one_async</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;_id&#39;</span><span class="p">:</span><span class="n">ObjectId</span><span class="p">(</span><span class="s">&#39;5059fb6b3d941cdc4487bdff&#39;</span><span class="p">)})</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;template.html&#39;</span><span class="p">,</span> <span class="n">post</span><span class="o">=</span><span class="n">thisPost</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>If you want to use callback-style development:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">myRequestHandler</span><span class="p">(</span><span class="n">MojoRequestHandler</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;template.html&#39;</span><span class="p">,</span> <span class="n">post</span><span class="o">=</span><span class="n">value</span><span class="p">)</span>
+
+ <span class="nd">@gen.engine</span>
+ <span class="nd">@tornado.web.asynchronous</span>
+ <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="kn">from</span> <span class="nn">bson.objectid</span> <span class="kn">import</span> <span class="n">ObjectId</span>
+ <span class="k">yield</span> <span class="n">gen</span><span class="o">.</span><span class="n">Task</span><span class="p">(</span><span class="n">BlogPost</span><span class="o">.</span><span class="n">find_one_async</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;_id&#39;</span><span class="p">:</span><span class="n">ObjectId</span><span class="p">(</span><span class="s">&#39;5059fb6b3d941cdc4487bdff&#39;</span><span class="p">)},</span> <span class="n">callback</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">)</span>
+</pre></div>
+</div>
+<p><strong>NOTE:</strong> The ORM and Models modules are still in very early stage development, please report any bugs to the developer on the
+source-control page on BitBucket.</p>
</div>
@@ -64,12 +204,23 @@
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
+ <h3><a href="../index.html">Table Of Contents</a></h3>
+ <ul>
+<li><a class="reference internal" href="#">The Mojo ORM and Models</a><ul>
+<li><a class="reference internal" href="#what-are-models">What are Models?</a></li>
+<li><a class="reference internal" href="#why-models">Why Models?</a></li>
+<li><a class="reference internal" href="#do-i-have-to-use-models">Do I have to use Models?</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#using-models">Using Models</a></li>
+</ul>
+
<h4>Previous topic</h4>
<p class="topless"><a href="urls.html"
title="previous chapter">Routing pages with URL&#8217;s</a></p>
<h4>Next topic</h4>
- <p class="topless"><a href="backends.html"
- title="next chapter">Using the Mojo backends</a></p>
+ <p class="topless"><a href="socketio.html"
+ title="next chapter">Mojo and SocketIO</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/models.txt"
@@ -102,7 +253,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="backends.html" title="Using the Mojo backends"
+ <a href="socketio.html" title="Mojo and SocketIO"
>next</a> |</li>
<li class="right" >
<a href="urls.html" title="Routing pages with URL’s"
View
18 Documentation/_build/html/docs/quickstart.html
@@ -26,7 +26,7 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="next" title="What are apps" href="apps.html" />
+ <link rel="next" title="Mojo Apps" href="apps.html" />
<link rel="prev" title="Mojo - a framework for Tornado" href="../index.html" />
</head>
<body>
@@ -40,7 +40,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="apps.html" title="What are apps"
+ <a href="apps.html" title="Mojo Apps"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../index.html" title="Mojo - a framework for Tornado"
@@ -56,7 +56,7 @@
<div class="section" id="quickstart-using-mojo-for-the-first-time">
<h1>Quickstart: Using Mojo for the first time<a class="headerlink" href="#quickstart-using-mojo-for-the-first-time" title="Permalink to this headline">¶</a></h1>
-<p>This is a quickstart tutorial that will get you set up and running with Mojo for the first time.</p>
+<p>This is a quick-start tutorial that will get you set up and running with Mojo for the first time.</p>
<div class="section" id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
<ol class="arabic simple">
@@ -66,15 +66,17 @@
<li>From the command line in the new folder run <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">install</span></tt></li>
</ol>
<p>This should install Mojo into your python path. However, there is one more step that you may need to do to fully
-take advantage of Mojo&#8217;s helper apps, and that is to make mojo_manager available in your PATH, for linux and Mac OSX users,
+take advantage of Mojo&#8217;s helper apps, and that is to make <tt class="docutils literal"><span class="pre">mojo_manager</span></tt> available in your <tt class="docutils literal"><span class="pre">PATH</span></tt>, for linux and Mac OSX users,
this can be accomplished by doing something like:</p>
-<div class="highlight-python"><pre>ln /usr/bin/python2.7/Lib/site-packages/Mojo/mojo_manager.py /usr/sbin/mojo_manager.py</pre>
+<div class="highlight-python"><pre>ln /usr/bin/python2.7/Lib/site-packages/Mojo/mojo_manager.py /usr/sbin/mojo_manager.py
+chmod +x /usr/sbin/mojo_manager.py</pre>
</div>
<p>On windows, adding the Mojo site-packages directory should be enough to give gloabl access to <tt class="docutils literal"><span class="pre">mojo_manager</span></tt></p>
<p>Once you&#8217;ve done that, you should be able to test your installation by opeining a python window and typing:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">Mojo</span>
</pre></div>
</div>
+<p>If there are no import errors then you shoulod be ready to get started.</p>
<p><em>Note:</em> It is recommended to deploy Mojo in something like virtualenv to ensure you can easily keep it (and your app)
up to date without affecting your main Python setup and other projects.</p>
</div>
@@ -129,7 +131,7 @@
</div>
<p>Once you&#8217;ve made the change, simply save the file and open up your terminal window in the directory where <tt class="docutils literal"><span class="pre">runserver.py</span></tt> is located, then
type the following:</p>
-<div class="highlight-python"><pre>``python runserver.py``</pre>
+<div class="highlight-python"><pre>python runserver.py</pre>
</div>
<p>You should see:</p>
<div class="highlight-python"><pre>Starting Mojo tornado server.
@@ -166,7 +168,7 @@
title="previous chapter">Mojo - a framework for Tornado</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="apps.html"
- title="next chapter">What are apps</a></p>
+ title="next chapter">Mojo Apps</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/quickstart.txt"
@@ -199,7 +201,7 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="apps.html" title="What are apps"
+ <a href="apps.html" title="Mojo Apps"
>next</a> |</li>
<li class="right" >
<a href="../index.html" title="Mojo - a framework for Tornado"
View
95 Documentation/_build/html/docs/socketio.html
@@ -8,7 +8,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Real Mojo: SocketIO &mdash; Mojo 0.1 documentation</title>
+ <title>Mojo and SocketIO &mdash; Mojo 0.1 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
@@ -26,8 +26,8 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="next" title="Using Mojo’s Auth module" href="authentication.html" />
- <link rel="prev" title="Using the Mojo backends" href="backends.html" />
+ <link rel="next" title="Using Mojo’s Auth and Session Mixins" href="authentication.html" />
+ <link rel="prev" title="The Mojo ORM and Models" href="models.html" />
</head>
<body>
<div class="related">
@@ -40,10 +40,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="authentication.html" title="Using Mojo’s Auth module"
+ <a href="authentication.html" title="Using Mojo’s Auth and Session Mixins"
accesskey="N">next</a> |</li>
<li class="right" >
- <a href="backends.html" title="Using the Mojo backends"
+ <a href="models.html" title="The Mojo ORM and Models"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
@@ -54,8 +54,67 @@
<div class="bodywrapper">
<div class="body">
- <div class="section" id="real-mojo-socketio">
-<h1>Real Mojo: SocketIO<a class="headerlink" href="#real-mojo-socketio" title="Permalink to this headline">¶</a></h1>
+ <div class="section" id="mojo-and-socketio">
+<h1>Mojo and SocketIO<a class="headerlink" href="#mojo-and-socketio" title="Permalink to this headline">¶</a></h1>
+<p>One of the strengths of Tornado is it&#8217;s ability to handle asynchronous requests and support for websockets. Top make Mojo
+more of a responsive framework, we&#8217;ve decided to bundle <tt class="docutils literal"><span class="pre">TornadIO2</span></tt> functionality as part of the overall package.</p>
+<p>For those that do not know what <tt class="docutils literal"><span class="pre">TornadIO2</span></tt> is, it is a <tt class="docutils literal"><span class="pre">SocketIO</span></tt> server implementation written in Python for Tornado, and
+makes it transparent to implement SocketIO clients into your app.</p>
+<p>By default, Mojo will start a <tt class="docutils literal"><span class="pre">TornadIO</span></tt> server for you that multiplexes a channel connection for each of the apps in your
+project.</p>
+<p>So if you have 2 apps: <tt class="docutils literal"><span class="pre">App1</span></tt> and <tt class="docutils literal"><span class="pre">App2</span></tt>, then you will be able to speak to either of these apps via SocketIO on the
+client by connecting to the <tt class="docutils literal"><span class="pre">/App1Socket</span></tt> or <tt class="docutils literal"><span class="pre">/App2Socket</span></tt> channels in your client side configuration.</p>
+<p>To configure what commands the server should intitiate on connection, send event or receive event, simply edit the <tt class="docutils literal"><span class="pre">socket_handlers.py</span></tt>
+file in your app folder:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">Mojo.SocketHandlers.BaseSocketHandler</span> <span class="kn">import</span> <span class="n">MojoSocketHandler</span><span class="p">,</span> <span class="n">CURRENT_SESSIONS</span><span class="p">,</span> <span class="n">LOGGED_IN_SESSIONS</span>
+
+<span class="c">#Setup your socket connections here</span>
+<span class="k">class</span> <span class="nc">SocketConnectionHandler</span><span class="p">(</span><span class="n">MojoSocketHandler</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
+ <span class="c">#Do something cool when a message arrives</span>
+ <span class="k">pass</span>
+</pre></div>
+</div>
+<p>To make the most of <tt class="docutils literal"><span class="pre">TornadIO2</span></tt> and <tt class="docutils literal"><span class="pre">SocketIO</span></tt> we&#8217;d recommend you read the documentation for both as their inner workings fall outside
+of the remit of the Mojo documentation.</p>
+<div class="section" id="helpful-tracking">
+<h2>Helpful Tracking<a class="headerlink" href="#helpful-tracking" title="Permalink to this headline">¶</a></h2>
+<p>Mojo does some handy tracking for you if you use the <tt class="docutils literal"><span class="pre">MojoSocketHandler</span></tt> to manage your socket connections. Mojo will
+automatically register all connections in two variables that enable you to communicate with users directly from the start,
+these variables are <tt class="docutils literal"><span class="pre">CURRENT_SESSIONS</span></tt> and <tt class="docutils literal"><span class="pre">LOGGED_IN_SESSIONS</span></tt></p>
+<div class="section" id="current-sessions">
+<h3><tt class="docutils literal"><span class="pre">CURRENT_SESSIONS</span></tt><a class="headerlink" href="#current-sessions" title="Permalink to this headline">¶</a></h3>
+<p>This is a dictionary object that will track each connection by their Session ID. The session ID is a secure Tornado cookie
+that is called <tt class="docutils literal"><span class="pre">session_id</span></tt>, if you are using the <tt class="docutils literal"><span class="pre">MojoSessionMixin</span></tt> module, this will be set for you, however if you
+want to roll your own session management, you can just set this cookie and the user will be tracked by the ID in the <tt class="docutils literal"><span class="pre">SocketHandler</span></tt>.</p>
+<p>This will enable you to do something like:</p>
+<div class="highlight-python"><pre>from Mojo.RequestHandlers.MojoHandler import MojoRequestHandler
+from Mojo.SocketHandlers.BaseSocketHandler import CURRENT_SESSIONS
+import json
+
+ class HelloWorldHandler(MojoRequestHandler):
+ def get(self, *args, **kwargs):
+
+ jsonObj = json.dumps({'data':'%s has joined the chat' % (self.session_id)})
+
+ for session in CURRENT_SESSIONS:
+ session.emit('joinedStatus', jsonObj)
+
+ self.render('hello.html')</pre>
+</div>
+<p>Although the above code is not functional, the principle is valid - in this example, you could use the CURRENT_SESSIONS object
+to broadcast to all active users that a new user has joined the conversation.</p>
+</div>
+<div class="section" id="logged-in-sessions">
+<h3><tt class="docutils literal"><span class="pre">LOGGED_IN_SESSIONS</span></tt><a class="headerlink" href="#logged-in-sessions" title="Permalink to this headline">¶</a></h3>
+<p>If you are using the AuthMixin from Mojo, then it will set an encrypted cookie of the name <tt class="docutils literal"><span class="pre">logged_in</span></tt> with the user ID
+of the current user. Naturally, you can set this yourself to whatever identifier you like if you decide not use the mixins.</p>
+<p>Any session that is identified as Logged in will be added to the <tt class="docutils literal"><span class="pre">LOGGED_IN_SESSIONS</span></tt> dictionary, and will enable you to
+interact with users. In a similar vein to the <tt class="docutils literal"><span class="pre">CURRENT_SESSIONS</span></tt> object, you would now be able to send specific messages only
+to logged in members of your app.</p>
+</div>
+</div>
</div>
@@ -64,12 +123,24 @@
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
+ <h3><a href="../index.html">Table Of Contents</a></h3>
+ <ul>
+<li><a class="reference internal" href="#">Mojo and SocketIO</a><ul>
+<li><a class="reference internal" href="#helpful-tracking">Helpful Tracking</a><ul>
+<li><a class="reference internal" href="#current-sessions"><tt class="docutils literal"><span class="pre">CURRENT_SESSIONS</span></tt></a></li>
+<li><a class="reference internal" href="#logged-in-sessions"><tt class="docutils literal"><span class="pre">LOGGED_IN_SESSIONS</span></tt></a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
<h4>Previous topic</h4>
- <p class="topless"><a href="backends.html"
- title="previous chapter">Using the Mojo backends</a></p>
+ <p class="topless"><a href="models.html"
+ title="previous chapter">The Mojo ORM and Models</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="authentication.html"
- title="next chapter">Using Mojo&#8217;s Auth module</a></p>
+ title="next chapter">Using Mojo&#8217;s Auth and Session Mixins</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/socketio.txt"
@@ -102,10 +173,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="authentication.html" title="Using Mojo’s Auth module"
+ <a href="authentication.html" title="Using Mojo’s Auth and Session Mixins"
>next</a> |</li>
<li class="right" >
- <a href="backends.html" title="Using the Mojo backends"
+ <a href="models.html" title="The Mojo ORM and Models"
>previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
View
32 Documentation/_build/html/docs/urls.html
@@ -26,8 +26,8 @@
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
- <link rel="next" title="Using the ORM and Models in your apps" href="models.html" />
- <link rel="prev" title="What are apps" href="apps.html" />
+ <link rel="next" title="The Mojo ORM and Models" href="models.html" />
+ <link rel="prev" title="Mojo Views" href="views.html" />
</head>
<body>
<div class="related">
@@ -40,10 +40,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="models.html" title="Using the ORM and Models in your apps"
+ <a href="models.html" title="The Mojo ORM and Models"
accesskey="N">next</a> |</li>
<li class="right" >
- <a href="apps.html" title="What are apps"
+ <a href="views.html" title="Mojo Views"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
@@ -56,6 +56,20 @@
<div class="section" id="routing-pages-with-url-s">
<h1>Routing pages with URL&#8217;s<a class="headerlink" href="#routing-pages-with-url-s" title="Permalink to this headline">¶</a></h1>
+<p>Mojo moves the URL definition of your app to the file <tt class="docutils literal"><span class="pre">urls.py</span></tt>, this file contains a list object called <tt class="docutils literal"><span class="pre">url_patterns</span></tt>
+that contains tuples mapping a URL to a <tt class="docutils literal"><span class="pre">RequestHandler</span></tt> in your <tt class="docutils literal"><span class="pre">views.py</span></tt>.</p>
+<p>All entries work the same way as they do with standard Tornado mappings, when your server starts up, Mojo will automatically
+concatenate all the URL&#8217;s for you into a single pattern set to ensure that all your apps are available in the project
+without mixing functionality across apps:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">views</span> <span class="kn">import</span> <span class="n">myRequestHandler</span>
+
+<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
+ <span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">,</span> <span class="n">myRequestHandler</span><span class="p">),</span>
+ <span class="p">]</span>
+</pre></div>
+</div>
+<p>All URL patterns can be regex groups - see the Tornado documentation for more details on how to use the URL routing
+in a Tornado app.</p>
</div>
@@ -65,11 +79,11 @@
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
- <p class="topless"><a href="apps.html"
- title="previous chapter">What are apps</a></p>
+ <p class="topless"><a href="views.html"
+ title="previous chapter">Mojo Views</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="models.html"
- title="next chapter">Using the ORM and Models in your apps</a></p>
+ title="next chapter">The Mojo ORM and Models</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/docs/urls.txt"
@@ -102,10 +116,10 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
- <a href="models.html" title="Using the ORM and Models in your apps"
+ <a href="models.html" title="The Mojo ORM and Models"
>next</a> |</li>
<li class="right" >
- <a href="apps.html" title="What are apps"
+ <a href="views.html" title="Mojo Views"
>previous</a> |</li>
<li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
</ul>
View
184 Documentation/_build/html/docs/views.html
@@ -0,0 +1,184 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <title>Mojo Views &mdash; Mojo 0.1 documentation</title>
+
+ <link rel="stylesheet" href="../_static/default.css" type="text/css" />
+ <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '../',
+ VERSION: '0.1',
+ COLLAPSE_INDEX: false,
+ FILE_SUFFIX: '.html',
+ HAS_SOURCE: true
+ };
+ </script>
+ <script type="text/javascript" src="../_static/jquery.js"></script>
+ <script type="text/javascript" src="../_static/underscore.js"></script>
+ <script type="text/javascript" src="../_static/doctools.js"></script>
+ <link rel="top" title="Mojo 0.1 documentation" href="../index.html" />
+ <link rel="next" title="Routing pages with URL’s" href="urls.html" />
+ <link rel="prev" title="Mojo Apps" href="apps.html" />
+ </head>
+ <body>
+ <div class="related">
+ <h3>Navigation</h3>
+ <ul>
+ <li class="right" style="margin-right: 10px">
+ <a href="../genindex.html" title="General Index"
+ accesskey="I">index</a></li>
+ <li class="right" >
+ <a href="../py-modindex.html" title="Python Module Index"
+ >modules</a> |</li>
+ <li class="right" >
+ <a href="urls.html" title="Routing pages with URL’s"
+ accesskey="N">next</a> |</li>
+ <li class="right" >
+ <a href="apps.html" title="Mojo Apps"
+ accesskey="P">previous</a> |</li>
+ <li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
+ </ul>
+ </div>
+
+ <div class="document">
+ <div class="documentwrapper">
+ <div class="bodywrapper">
+ <div class="body">
+
+ <div class="section" id="mojo-views">
+<h1>Mojo Views<a class="headerlink" href="#mojo-views" title="Permalink to this headline">¶</a></h1>
+<p>Mojo views are where you will write most of your application and page handling logic. In the <tt class="docutils literal"><span class="pre">views.py</span></tt> file, you will
+sub-clas the MojoRequestHandler class to create your application.</p>
+<p>The MojoRequestHandler is a slightly modified version of the basic Tornado RequestHandler that makes the local templates available to
+the interpreter and adds support for prettier error formatting, it is also required to make the <tt class="docutils literal"><span class="pre">SessionMixin</span></tt> and <tt class="docutils literal"><span class="pre">AuthMixin</span></tt>
+classes to work as they depend on the <tt class="docutils literal"><span class="pre">MojoRequestHandler</span></tt> base class.</p>
+<p><em>Note:</em> It completely possible to develop with Mojo using standard <tt class="docutils literal"><span class="pre">equestHandlers</span></tt>, simply subclass them as you would normally
+and use them in your <tt class="docutils literal"><span class="pre">urls.py</span></tt></p>
+<div class="section" id="views-quick-start">
+<h2>Views Quick-start:<a class="headerlink" href="#views-quick-start" title="Permalink to this headline">¶</a></h2>
+<p>To write your first view, subclas the MojoRequestHandler class, type thi into your view handler:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">Mojo.RequestHandlers.MojoHandler</span> <span class="kn">import</span> <span class="n">MojoRequestHandler</span>
+
+<span class="k">class</span> <span class="nc">HelloWorldHandler</span><span class="p">(</span><span class="n">MojoRequestHandler</span><span class="p">):</span>
+ <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s">&#39;hello.html&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>And then mak sure it is accessible in your <tt class="docutils literal"><span class="pre">urls.py</span></tt> file:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">views</span> <span class="kn">import</span> <span class="o">*</span>
+
+<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
+ <span class="c">#Place your URL Routes / RequestHandler mappings in here for this app, e.g.</span>
+ <span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="n">HelloWorldHandler</span><span class="p">),</span>
+<span class="p">]</span>
+</pre></div>
+</div>
+<p>You will also need to actually create the template file, <tt class="docutils literal"><span class="pre">hello.html</span></tt>, it could lok somwthing like this:</p>
+<div class="highlight-python"><pre>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd"&gt;
+&lt;html&gt;
+&lt;head&gt;
+ &lt;title&gt;Hello from Mojo!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+ &lt;h1&gt;Hi there, I'm a template inside Mojo!&lt;/h1&gt;
+ &lt;p&gt;This is a tempalte file that is stored in your apps template directory.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;</pre>
+</div>
+<dl class="docutils">
+<dt>Save this file to your app <tt class="docutils literal"><span class="pre">templates</span></tt> directory and make sure that your app is listed in the <tt class="docutils literal"><span class="pre">settings.py</span></tt> <tt class="docutils literal"><span class="pre">INSTALLED_APPS</span></tt></dt>
+<dd><p class="first">setting:</p>
+<div class="last highlight-python"><div class="highlight"><pre><span class="n">INSTALLED_APPS</span> <span class="o">=</span> <span class="p">[</span>
+ <span class="s">&#39;HelloWorldApp&#39;</span><span class="p">,</span>
+<span class="p">]</span>
+</pre></div>
+</div>
+</dd>
+</dl>
+<p>Now you just need to run your server, in a command line window, in your project directory type:</p>
+<div class="highlight-python"><pre>python runserver.py</pre>
+</div>
+<p>If your server is already running, and you have <tt class="docutils literal"><span class="pre">DEBUG=True</span></tt> set in your <tt class="docutils literal"><span class="pre">settings.py</span></tt> file, it should automatically restart when you save
+the above changes.</p>
+<p>When you navigate to <tt class="docutils literal"><span class="pre">http://localhost:8000/</span></tt> you should see your template being rendered out...</p>
+<p>The MojoRequestHandler behaves the same way as the Tornado request handler, we recommend the reader check the Tornado documentation
+to get fully up to speed with what the capabilities are of <tt class="docutils literal"><span class="pre">RequestHandler</span></tt> objects.</p>
+</div>
+</div>
+
+
+ </div>
+ </div>
+ </div>
+ <div class="sphinxsidebar">
+ <div class="sphinxsidebarwrapper">
+ <h3><a href="../index.html">Table Of Contents</a></h3>
+ <ul>
+<li><a class="reference internal" href="#">Mojo Views</a><ul>
+<li><a class="reference internal" href="#views-quick-start">Views Quick-start:</a></li>
+</ul>
+</li>
+</ul>
+
+ <h4>Previous topic</h4>
+ <p class="topless"><a href="apps.html"
+ title="previous chapter">Mojo Apps</a></p>
+ <h4>Next topic</h4>
+ <p class="topless"><a href="urls.html"
+ title="next chapter">Routing pages with URL&#8217;s</a></p>
+ <h3>This Page</h3>
+ <ul class="this-page-menu">
+ <li><a href="../_sources/docs/views.txt"
+ rel="nofollow">Show Source</a></li>
+ </ul>
+<div id="searchbox" style="display: none">
+ <h3>Quick search</h3>
+ <form class="search" action="../search.html" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="Go" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ Enter search terms or a module, class or function name.
+ </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+ </div>
+ </div>
+ <div class="clearer"></div>
+ </div>
+ <div class="related">
+ <h3>Navigation</h3>
+ <ul>
+ <li class="right" style="margin-right: 10px">
+ <a href="../genindex.html" title="General Index"
+ >index</a></li>
+ <li class="right" >
+ <a href="../py-modindex.html" title="Python Module Index"
+ >modules</a> |</li>
+ <li class="right" >
+ <a href="urls.html" title="Routing pages with URL’s"
+ >next</a> |</li>
+ <li class="right" >
+ <a href="apps.html" title="Mojo Apps"
+ >previous</a> |</li>
+ <li><a href="../index.html">Mojo 0.1 documentation</a> &raquo;</li>
+ </ul>
+ </div>
+ <div class="footer">
+ &copy; Copyright 2012, Martin Buhr.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
+ </div>
+ </body>
+</html>
View
26 Documentation/_build/html/index.html
@@ -77,12 +77,28 @@
<li class="toctree-l2"><a class="reference internal" href="docs/quickstart.html#setup-the-app">Setup the App</a></li>
</ul>
</li>
-<li class="toctree-l1"><a class="reference internal" href="docs/apps.html">What are apps</a></li>
+<li class="toctree-l1"><a class="reference internal" href="docs/apps.html">Mojo Apps</a></li>
+<li class="toctree-l1"><a class="reference internal" href="docs/views.html">Mojo Views</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="docs/views.html#views-quick-start">Views Quick-start:</a></li>
+</ul>
+</li>
<li class="toctree-l1"><a class="reference internal" href="docs/urls.html">Routing pages with URL&#8217;s</a></li>
-<li class="toctree-l1"><a class="reference internal" href="docs/models.html">Using the ORM and Models in your apps</a></li>
-<li class="toctree-l1"><a class="reference internal" href="docs/backends.html">Using the Mojo backends</a></li>
-<li class="toctree-l1"><a class="reference internal" href="docs/socketio.html">Real Mojo: SocketIO</a></li>
-<li class="toctree-l1"><a class="reference internal" href="docs/authentication.html">Using Mojo&#8217;s Auth module</a></li>
+<li class="toctree-l1"><a class="reference internal" href="docs/models.html">The Mojo ORM and Models</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="docs/models.html#what-are-models">What are Models?</a></li>
+<li class="toctree-l2"><a class="reference internal" href="docs/models.html#why-models">Why Models?</a></li>
+<li class="toctree-l2"><a class="reference internal" href="docs/models.html#do-i-have-to-use-models">Do I have to use Models?</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="docs/models.html#using-models">Using Models</a></li>
+<li class="toctree-l1"><a class="reference internal" href="docs/socketio.html">Mojo and SocketIO</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="docs/socketio.html#helpful-tracking">Helpful Tracking</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="docs/authentication.html">Using Mojo&#8217;s Auth and Session Mixins</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="docs/authentication.html#authmixin">AuthMixin</a></li>
+<li class="toctree-l2"><a class="reference internal" href="docs/authentication.html#the-sessionmixin">The SessionMixin</a></li>
+</ul>
+</li>
</ul>
</div>
</div>
View
BIN  Documentation/_build/html/objects.inv
Binary file not shown
View
2  Documentation/_build/html/searchindex.js
@@ -1 +1 @@
-Search.setIndex({objects:{"Mojo.Auth.SessionManager":{Reset_session:[3,1,1,""],Setup_session:[3,1,1,""],SessionManager:[3,2,1,""]},"Mojo.Backends":{base_interface:[6,0,1,""]},"Mojo.Auth.Mixins.MojoAuthMixin":{MojoAuthMixin:[8,2,1,""]},"Mojo.ObjectMapper":{FieldPrototype:[13,0,1,""],Fields:[13,0,1,""]},"Mojo.ObjectMapper.ModelPrototype":{EmbeddedModelField:[13,2,1,""],Model:[13,2,1,""]},"Mojo.ObjectMapper.FieldPrototype":{Field:[13,2,1,""]},"Mojo.SocketHandlers.BaseSocketHandler":{MojoSocketHandler:[2,2,1,""]},"Mojo.ObjectMapper.Fields.ObjectIDField":{base_type:[13,4,1,""]},"Mojo.Backends.base_interface.CollectionModelInterface":{find_one:[6,3,1,""],insert:[6,3,1,""],save:[6,3,1,""],find:[6,3,1,""],"delete":[6,3,1,""]},"Mojo.Auth.Mixins":{MojoAuthMixin:[8,0,1,""]},"Mojo.ObjectMapper.Fields.BooleanField":{get_value:[13,3,1,""],base_type:[13,4,1,""]},"Mojo.ObjectMapper.FieldPrototype.Field":{validate:[13,3,1,""],get_value:[13,3,1,""],validate_type:[13,3,1,""],validate_is_null:[13,3,1,""]},"Mojo.Auth.SessionManager.SessionManager":{"_get_session_key":[3,3,1,""],"_decode_session":[3,3,1,""],"_set_session_key":[3,3,1,""],"_is_session_valid":[3,3,1,""],get_session_cookies:[3,3,1,""],"_logout":[3,3,1,""],"_is_logged_in":[3,3,1,""],"_login":[3,3,1,""],"_encode_session":[3,3,1,""],"_create_new_session":[3,3,1,""]},"Mojo.ObjectMapper.Fields.FloatField":{base_type:[13,4,1,""]},"Mojo.Auth.AuthManager":{authenticate:[3,1,1,""],remove_from_group:[3,1,1,""],make_random_password:[3,1,1,""],login:[3,1,1,""],is_member_of:[3,1,1,""],set_password:[3,1,1,""],add_to_group:[3,1,1,""]},"Mojo.ObjectMapper.Fields.ListField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.Fields.IntegerField":{base_type:[13,4,1,""]},"Mojo.Auth.Helpers":{login_assistant:[3,1,1,""],logout_assistant:[3,1,1,""]},"Mojo.ObjectMapper.Fields":{DateTimeField:[13,2,1,""],ListField:[13,2,1,""],IntegerField:[13,2,1,""],StringField:[13,2,1,""],FloatField:[13,2,1,""],ObjectIDField:[13,2,1,""],BooleanField:[13,2,1,""]},"Mojo.Auth.Mixins.SessionMixins.SessionMixin_Async":{get_session_key:[8,3,1,""],set_session_key:[8,3,1,""],get_session_object:[8,3,1,""],session:[8,4,1,""],get_user_from_db:[8,3,1,""],save_session_object:[8,3,1,""],create_new_session:[8,3,1,""]},"Mojo.ObjectMapper.Fields.StringField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.Fields.DateTimeField":{base_type:[13,4,1,""]},"Mojo.SocketHandlers":{BaseSocketHandler:[2,0,1,""]},"Mojo.Auth.Mixins.SessionMixins.SessionMixin_Sync":{get_session_key:[8,3,1,""],set_session_key:[8,3,1,""],get_session_object:[8,3,1,""],session:[8,4,1,""],get_user_from_db:[8,3,1,""],save_session_object:[8,3,1,""],create_new_session:[8,3,1,""]},"Mojo.Auth.models":{Profile:[3,2,1,""],Session:[3,2,1,""],Group:[3,2,1,""],User:[3,2,1,""]},"Mojo.Auth":{models:[3,0,1,""],Helpers:[3,0,1,""],AuthManager:[3,0,1,""],SessionManager:[3,0,1,""]},"Mojo.Auth.Mixins.SessionMixins":{SessionMixin_Async:[8,2,1,""],SessionMixin_Sync:[8,2,1,""]},"Mojo.RequestHandlers.MojoHandler":{MojoRequestHandler:[7,2,1,""]},"Mojo.ObjectMapper.ModelPrototype.EmbeddedModelField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.ModelPrototype.Model":{validate:[13,3,1,""],insert:[13,5,1,""],delete_bulk:[13,5,1,""],delete_bulk_async:[13,5,1,""],find_one:[13,5,1,""],insert_async:[13,5,1,""],get_value:[13,3,1,""],find_one_async:[13,5,1,""],save_async:[13,3,1,""],find_async:[13,5,1,""],save:[13,3,1,""],delete_async:[13,3,1,""],find:[13,5,1,""],"delete":[13,3,1,""]},"Mojo.Backends.base_interface":{CollectionModelInterface:[6,2,1,""],SessionInterface:[6,2,1,""]},"Mojo.RequestHandlers":{MojoHandler:[7,0,1,""]},"Mojo.Auth.Mixins.MojoAuthMixin.MojoAuthMixin":{get_current_user:[8,3,1,""]}},terms:{represent:[3,13],all:[2,3,6,7,10,13],code:0,chain:13,osx:10,queri:[3,13],global:2,managem:8,runserv:10,abil:0,follow:[10,6],content:0,decid:6,depend:[3,13],current_us:[3,8],mojorequesthandl:[7,6,8],base64:3,friendli:13,init:3,collectionmodelinterfac:6,get_user_from_db:8,under:13,base_typ:13,digit:3,sourc:13,everi:[3,7],string:[3,13],straightforward:8,fals:[3,13,6],on_messag:2,this_us:6,affect:10,strang:10,cool:7,hous:10,list:[3,13,6],"try":[13,6],item:13,cooki:[3,2,8],tru:3,round:3,direct:[7,6],design:[3,6,8],pass:2,download:10,bake:0,port:[10,6],compat:8,index:0,what:[10,0,13,6,11],this_field:13,section:[3,10],abl:[10,6],"while":[3,6],current:[3,6,8],delet:[13,6],"_get_valu":13,last_login:3,modelprototyp:[13,6],helloworldapp:10,"new":[0,3,6,8,10,13],ascii:3,method:[3,13,8],full:[13,8],gener:[3,2],here:[10,13,2],behaviour:13,met:13,let:[10,13],address:3,socketconnectionhandl:2,valu:[3,13,8],login_assist:[3,8],search:0,base_interfac:6,mojo_set:7,reason:6,host:6,datetim:13,orm:[0,13,4,8],make_random_password:3,another_field:13,chang:[3,10,13,6],via:[6,8],appli:3,app:[10,0,4,11],prefer:8,is_authent:3,schemaless:13,api:0,instal:[3,0,10,6],coercion:13,unit:10,mongo:[3,13],from:[0,2,3,6,8,10,13],describ:6,would:13,stringfield:13,two:[13,2,6,8],date_join:3,next:8,sessionobj:3,find_one_async:[13,6],call:[3,13,2,6],usr:10,recommend:[10,6],msg:2,expiri:3,type:[10,0,13],start:[10,0,7],minor:6,more:[3,7,10,13],to_insert:13,alphabet:3,function_nam:6,flag:3,indic:[3,0],hold:8,basesockethandl:2,must:13,none:[2,3,6,8,7,13],endpoint:2,join:3,hour:3,socketio:[0,12],alia:13,setup:[10,0,2,6],work:[10,8],itself:8,can:[0,2,3,6,7,10,13],sessionmixin_sync:[7,8],purpos:[13,8],root:10,def:[13,7,2,6,8],overrid:[13,2,6,8],"_is_session_valid":3,favourit:10,quickstart:[10,0],objectid:[3,13],give:[10,7],process:3,insert_async:13,templat:[10,0,6,8],minimum:13,want:[3,7,10,13],onlin:2,keep:10,blog_app:10,multipl:[3,13],secur:[3,8],anoth:[3,10,2],write:[0,6],how:3,instead:[7,6,8],simpl:[13,2,8],this_session_valu:8,map:13,overridden:13,mojo_blog:10,after:3,variant:13,them:[3,13],befor:13,mac:10,socket:2,mixin:[3,0,8,7],retain:6,mai:10,end:[13,6],associ:6,essenti:[3,6],third:0,classmethod:13,explicit:13,validate_is_nul:13,django:0,callback:8,maintain:3,allow:[3,13],enter:10,order:[3,6],least:6,help:3,allow_empti:13,familli:8,through:[3,7,6],flexibl:0,mainli:[3,13],whatever_field:13,paramet:[3,13,6],snippet:6,style:[13,6,8],group:[3,10],render:[7,6,8],nifti:8,chosen:[3,13],"__class__":13,relev:[3,10,13,6],window:10,html:[7,6,8],mytestmodel:13,persist:[3,8],depopul:2,main:[3,10,13,8],alter:0,finer:13,non:[3,13,6,8],"return":[3,13,6,8],thei:[10,7,13,8],python:10,encod:[3,8],safe:6,dai:3,auth:[0,2,3,6,8,9],"break":10,framework:[3,0,2,13],db_name:6,funciton:8,now:13,introduct:[],name:[3,6],valud:3,authent:[3,0,8],easili:[10,6],exampl:[3,13,6,8],each:[10,13,8],debug:[10,0],fulli:[10,6,8],unicod:13,mean:13,individu:10,ensur:[10,13,6,8],"static":10,expect:[13,6],mojo_manag:10,our:13,event:2,out:[3,10,13],variabl:[7,13,8],ictionari:[],shown:13,accomplish:[3,10],typecast:13,influenc:0,profil:3,rewrit:6,print:[13,6],correct:13,common:[2,8],navig:10,state:3,manipul:3,standard:[13,7,2,8],quick:[10,0,8],on_clos:2,base:[0,2,3,6,8,10,13],dictionari:[13,2,6],basi:0,projct:10,acquaint:0,get_session_cooki:3,delete_async:13,omit:13,synchron:[3,8],success:3,static_url:10,initialis:[3,8],datetimefield:[3,13],thing:[3,13],length:13,place:10,router:10,my_data:13,bakend:[],assign:[13,6,8],first:[10,0,6,8],oper:[13,8],directli:[3,10,13],onc:[3,10],dure:6,independ:10,sessioninterfac:6,date:[3,10],unlik:13,alreadi:8,done:10,wrapper:[6,8],blank:3,installed_app:10,open:10,mojo:[0,2,3,6,5,7,8,9,10,12,13],hood:13,differ:[10,13,6],convent:0,projectnam:10,data:[0,2,3,6,8,13],interact:6,linenothreshold:[],system:[3,0],messag:2,tradition:13,max_length:13,similarli:8,logged_in:[3,2,8],conveni:2,store:[3,13,2,8],schema:6,adher:6,option:[3,13],asyncmongo:6,namespac:13,tool:[3,6],broadcast:2,sraightforward:6,part:[3,13,6,8],accompani:3,"_logout":3,termin:10,than:13,png:10,machineri:8,serv:7,target:8,provid:[3,8],remov:[3,13],requesthandl:[3,0,8,7],logout_assist:3,structur:[10,0,13],charact:[3,13],project:[10,0,6,7],expiry_dai:3,mojohandl:[7,8],minut:3,treanslat:6,seri:[3,10],save_async:13,well:13,validate_max_length:13,is_member_of:3,ani:[3,7,6,8],find_on:[3,13,6,8],raw:13,expir:3,have:[10,13,6,8],tabl:[10,0],need:[3,0,10,13,7],"_async":6,objectmapp:[0,13,6],engin:[6,8],built:[10,13],thisus:[3,13,8],inform:[3,6,8],self:[2,3,6,8,7,13],note:[10,13],mix:3,discret:10,take:[3,10,13,6,8],which:[13,6,8],bcrypt:[3,10],singl:13,uppercas:3,ioloop:10,sure:[10,6],distribut:10,integerfield:13,get_current_us:[3,8],tornado:[0,3,6,8,7,10],"504e0439a9ee2f04a0835a92":3,subtyp:13,most:[],regular:[6,8],automodul:[],deploi:10,"class":[2,3,6,8,7,13],tradit:6,don:[0,7],url:[10,0,1,7],"_return_model_object":6,request:[3,7,10,2,8],wtform:[10,0],doe:3,declar:7,prettier:0,determin:3,"_id":3,dot:13,max_valu:13,text:13,"__str__":13,random:3,new_sess:3,session:[0,2,3,6,8,7,10],get_session_kei:8,"_login":3,fine:13,find:[0,13,6],make:[0,2,3,6,8,7,10],redirect:8,access:[10,7,13,6,8],onli:[3,2,6],coerc:13,locat:10,activ:3,written:6,should:[3,10,13,8],dict:[3,13],folder:10,meant:3,reset:3,hit:3,min_valu:13,variou:10,get:[0,3,6,8,7,10,13],familiar:0,sesionmanag:3,solut:13,return_dict:6,cannot:3,"_set_session_kei":3,gen:[13,6,8],requir:[3,10,2,13],remove_from_group:3,mapper:[13,6],enabl:[13,0,2,6,8],yield:[13,6,8],email:3,stuff:7,integr:[3,0,13,6],contain:[10,13],where:10,view:10,set:[0,2,3,6,8,7,10,13],creator:6,on_open:2,model_inst:13,see:[3,0,10,13,8],arg:[13,6,8],fail:8,close:6,setup_sess:3,statu:[3,2],kei:[3,0,2,8],helper:[3,0,10,8],databas:[0,3,6,8,7,10,13],someth:10,tend:6,enough:[10,6],"import":[3,10,13,2,8],awai:[10,6],across:3,attribut:3,ui_modul:10,extend:[3,0,13],conjunct:3,nbame:10,entir:13,len:13,objectidfield:13,find_async:13,come:[13,8],"__unicode__":13,get_valu:13,both:6,last:3,expos:[13,2,6,8],session_model:[3,8],admin:8,booleanfield:[3,13],howev:10,against:3,groupobj:3,etc:6,tutori:10,grain:13,context:8,logic:13,mani:[7,6],eth:10,whole:8,load:[10,8],simpli:[10,8],point:7,instanti:13,littl:13,suppli:8,path:[10,6],typic:10,guid:0,backend:[0,6,5,8],flooat:[],user_id:2,creat:[3,10,13,6,8],is_superus:3,sessionmixin_async:[6,8],three:3,been:13,json:3,much:2,basic:[7,13,6],popul:[0,2],valueerror:13,life:7,imag:10,expiry_hour:3,floatfield:13,valididti:3,togeth:13,input:[3,13,6],"case":[3,8],look:10,get_argu:8,packag:10,properti:[7,13,6,8],batch:13,easier:[3,7],defin:13,invok:10,sockethandl:[10,0,2],outcom:3,abov:[13,6],error:[7,8],login:[3,7,8],real:[0,12],sessionmixin:[3,7,8],file:[10,7,6],advantag:[10,13,8],readi:3,"_is_logged_in":3,site:[10,2],kwarg:[7,13,6,8],lightweight:0,test_valu:8,"__init__":13,around:[13,6,8],parent:13,"null":13,develop:[0,6,7],welcom:10,perform:3,parti:0,new_password:3,belong:3,same:[3,13],member:3,embeddedmodelfield:13,instanc:13,decod:3,authmanag:[3,0],set_session_kei:8,document:[3,13,6],behav:13,session_valu:8,http:10,referenc:[10,6],nest:13,assist:8,driver:[3,7,6,8],loginhandl:8,decompress:10,sessionmanag:[3,8],rais:13,user:[2,3,6,8,10,13],implement:[0,13,6,8],expand:[7,13],lib:10,task:[13,2,6,8],off:[3,0],gloabl:10,fieldprototyp:13,inherit:13,without:[10,0,13,6,8],client:2,command:10,thi:[2,3,6,8,7,10,13],model:[0,3,4,8,6,10,13],mojoauthmixin:[3,7,6,8],rout:[0,1],validate_typ:13,identifi:8,just:6,boot:6,modular:0,userobj:3,heavili:0,uid:8,web:[10,6,8],curent_us:3,easi:[3,0,13,6,8],also:[3,13,8],recurs:13,shoul:3,get_session_object:8,usernam:[3,13,6,8],shortcut:3,"_get_session_kei":3,add:[3,0,13,6],other:[10,0,13,6],embeddedfield:13,els:[3,13,8],har:6,save:[3,10,13,6,8],modul:[0,2,3,6,8,9,10],match:3,build:0,bin:10,applic:[10,7,8],request_handl:3,asyncmongobackend:6,format:6,amp:10,bit:6,password:[3,8],set_password:3,python2:10,linux:10,insert:[13,6],"_setup_connect":6,like:[10,13],specif:[3,13,2,6,8],reset_sess:3,signal:2,manual:8,integ:13,server:[10,7,6],collect:[13,8],paramat:[3,13],either:[3,8],martin:6,output:[0,13],is_async:6,manag:[0,2,3,8,7,10],underli:13,login_assit:3,uder:3,creation:0,some:[0,2,13,7],back:[13,6,8],intern:[3,13],logged_in_sess:2,librari:3,add_to_group:3,virtualenv:10,throughout:13,listfield:[3,13],leak:8,avoid:3,definit:[3,10,13],subclass:[13,7,2,6,8],save_session_object:8,exisitng:3,localhost:10,refer:7,object:[3,7,13,6,8],run:[10,13],"_encode_sess":3,usag:[3,13,2,6,8],collection_nam:6,step:10,to_delet:13,found:10,"__name__":13,post:8,"super":[3,13],"throw":13,handi:7,simpler:2,sbin:10,zip:10,world:[13,8],bahva:[],page:[10,0,1,8],includ:[0,13,6],commit:13,produc:13,block:[3,13,6,8],tornadio2:[10,0,2],own:[3,0,13,6],"float":13,som:13,bound:13,automat:[3,10,2,8],appropri:[3,10,6],down:[10,6],empti:13,expiry_minut:3,wrap:8,bson:13,bool:13,storag:13,your:[0,2,4,8,6,7,10,13],log:[3,2,8],wai:[10,13,8],area:10,support:[10,0,6],"long":3,custom:13,avail:[10,2,6,8],strict:13,handler:[10,7],interfac:6,editor:10,lot:7,strictli:13,"_db":[7,6],asset:10,"function":[0,3,6,8,7,10,13],create_new_sess:8,delete_bulk_async:13,form:[0,13],offer:[10,13,6,8],forc:6,serverhelp:[],shorter:13,pagehandl:7,line:10,"true":[3,13],congratul:10,info:10,made:[10,2],flavour:8,consist:[3,13,8],possibl:13,"default":[3,0,13,8],mojosockethandl:2,maximum:13,troubl:13,asynchron:[3,13,6,8],opein:10,highlight:[],embed:[3,13],similar:6,emit:2,connect:[2,6],socketconnect:2,featur:[0,8],alongsid:[3,8],evalu:13,sesison:[3,8],"int":13,retriev:13,"abstract":6,doesn:3,repres:[3,13],current_sess:2,intro:[],exist:[3,13],session_id:[3,2,8],chat:2,logo:10,pip:6,ship:6,check:[3,13,2,8],again:3,encrypt:3,new_model_inst:13,titl:[],when:[3,10,13],new_valu:8,field:[3,0,13],"_decode_sess":3,valid:[3,13],lookup:3,rememb:2,test:[10,6],you:[0,2,3,6,7,10,13],pymongo:[13,6],roll:0,mongodb:[13,6],asyncmongo_backend:6,thishandl:6,scale:0,track:3,establish:13,veri:0,delete_bulk:13,session_data:3,"_create_new_sess":[3,8],directori:10,rule:13,klass:13,time:[3,0,10],mynewproject:10,tornadio:10,hello:[13,8],prototyp:6},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:method","4":"py:attribute","5":"py:classmethod"},titles:["Mojo - a framework for Tornado","Routing pages with URL&#8217;s","Mojo.SocketHandlers","Mojo.Auth","Using the ORM and Models in your apps","Using the Mojo backends","Mojo.Backends","Mojo.RequestHandlers","Mojo.Auth.Mixins","Using Mojo&#8217;s Auth module","Quickstart: Using Mojo for the first time","What are apps","Real Mojo: SocketIO","Mojo.ObjectMapper"],objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","method","Python method"],"4":["py","attribute","Python attribute"],"5":["py","classmethod","Python class method"]},filenames:["index","docs/urls","docs/api/SocketHandlers","docs/api/Auth","docs/models","docs/backends","docs/api/Backends","docs/api/RequestHandlers","docs/api/Mixins","docs/authentication","docs/quickstart","docs/apps","docs/socketio","docs/api/ObjectMapper"]})
+Search.setIndex({objects:{"Mojo.Auth.SessionManager":{Reset_session:[4,1,1,""],Setup_session:[4,1,1,""],SessionManager:[4,2,1,""]},"Mojo.Backends":{base_interface:[7,0,1,""]},"Mojo.Auth.Mixins.MojoAuthMixin":{MojoAuthMixin:[6,2,1,""]},"Mojo.ObjectMapper":{FieldPrototype:[13,0,1,""],Fields:[13,0,1,""]},"Mojo.ObjectMapper.ModelPrototype":{EmbeddedModelField:[13,2,1,""],Model:[13,2,1,""]},"Mojo.ObjectMapper.FieldPrototype":{Field:[13,2,1,""]},"Mojo.SocketHandlers.BaseSocketHandler":{MojoSocketHandler:[3,2,1,""]},"Mojo.ObjectMapper.Fields.ObjectIDField":{base_type:[13,4,1,""]},"Mojo.Backends.base_interface.CollectionModelInterface":{find_one:[7,3,1,""],insert:[7,3,1,""],save:[7,3,1,""],find:[7,3,1,""],"delete":[7,3,1,""]},"Mojo.Auth.Mixins":{MojoAuthMixin:[6,0,1,""]},"Mojo.ObjectMapper.Fields.BooleanField":{get_value:[13,3,1,""],base_type:[13,4,1,""]},"Mojo.ObjectMapper.FieldPrototype.Field":{validate:[13,3,1,""],get_value:[13,3,1,""],validate_type:[13,3,1,""],validate_is_null:[13,3,1,""]},"Mojo.Auth.SessionManager.SessionManager":{"_get_session_key":[4,3,1,""],"_decode_session":[4,3,1,""],"_set_session_key":[4,3,1,""],"_is_session_valid":[4,3,1,""],get_session_cookies:[4,3,1,""],"_logout":[4,3,1,""],"_is_logged_in":[4,3,1,""],"_login":[4,3,1,""],"_encode_session":[4,3,1,""],"_create_new_session":[4,3,1,""]},"Mojo.ObjectMapper.Fields.FloatField":{base_type:[13,4,1,""]},"Mojo.Auth.AuthManager":{authenticate:[4,1,1,""],remove_from_group:[4,1,1,""],make_random_password:[4,1,1,""],login:[4,1,1,""],is_member_of:[4,1,1,""],set_password:[4,1,1,""],add_to_group:[4,1,1,""]},"Mojo.ObjectMapper.Fields.ListField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.Fields.IntegerField":{base_type:[13,4,1,""]},"Mojo.Auth.Helpers":{login_assistant:[4,1,1,""],logout_assistant:[4,1,1,""]},"Mojo.ObjectMapper.Fields":{DateTimeField:[13,2,1,""],ListField:[13,2,1,""],IntegerField:[13,2,1,""],StringField:[13,2,1,""],FloatField:[13,2,1,""],ObjectIDField:[13,2,1,""],BooleanField:[13,2,1,""]},"Mojo.Auth.Mixins.SessionMixins.SessionMixin_Async":{get_session_key:[6,3,1,""],set_session_key:[6,3,1,""],get_session_object:[6,3,1,""],session:[6,4,1,""],get_user_from_db:[6,3,1,""],save_session_object:[6,3,1,""],create_new_session:[6,3,1,""]},"Mojo.ObjectMapper.Fields.StringField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.Fields.DateTimeField":{base_type:[13,4,1,""]},"Mojo.SocketHandlers":{BaseSocketHandler:[3,0,1,""]},"Mojo.Auth.Mixins.SessionMixins.SessionMixin_Sync":{get_session_key:[6,3,1,""],set_session_key:[6,3,1,""],get_session_object:[6,3,1,""],session:[6,4,1,""],get_user_from_db:[6,3,1,""],save_session_object:[6,3,1,""],create_new_session:[6,3,1,""]},"Mojo.Auth.models":{Profile:[4,2,1,""],Session:[4,2,1,""],Group:[4,2,1,""],User:[4,2,1,""]},"Mojo.Auth":{models:[4,0,1,""],Helpers:[4,0,1,""],AuthManager:[4,0,1,""],SessionManager:[4,0,1,""]},"Mojo.Auth.Mixins.SessionMixins":{SessionMixin_Async:[6,2,1,""],SessionMixin_Sync:[6,2,1,""]},"Mojo.RequestHandlers.MojoHandler":{MojoRequestHandler:[8,2,1,""]},"Mojo.ObjectMapper.ModelPrototype.EmbeddedModelField":{base_type:[13,4,1,""]},"Mojo.ObjectMapper.ModelPrototype.Model":{validate:[13,3,1,""],insert:[13,5,1,""],delete_bulk:[13,5,1,""],delete_bulk_async:[13,5,1,""],find_one:[13,5,1,""],insert_async:[13,5,1,""],get_value:[13,3,1,""],find_one_async:[13,5,1,""],save_async:[13,3,1,""],find_async:[13,5,1,""],save:[13,3,1,""],delete_async:[13,3,1,""],find:[13,5,1,""],"delete":[13,3,1,""]},"Mojo.Backends.base_interface":{CollectionModelInterface:[7,2,1,""],SessionInterface:[7,2,1,""]},"Mojo.RequestHandlers":{MojoHandler:[8,0,1,""]},"Mojo.Auth.Mixins.MojoAuthMixin.MojoAuthMixin":{get_current_user:[6,3,1,""]}},terms:{represent:[4,13],all:[2,3,4,5,7,8,9,10,12,13],code:[1,12,5],chain:13,osx:10,queri:[4,13,5],global:3,managem:6,runserv:[0,10],abil:[1,12,5],follow:[10,5,7],lookup:4,profil:4,decid:[12,7],specif:[3,4,7,6,12,13],depend:[0,4,13,9],advantag:[10,13,6],current_us:[4,6,9],mojorequesthandl:[0,5,6,7,8,9,12],base64:[4,9],readabl:5,friendli:13,send:12,init:4,collectionmodelinterfac:7,becam:5,get_user_from_db:6,under:[11,13],base_typ:13,helloworldhandl:[0,12],digit:4,sourc:[13,5],everi:[4,8],string:[4,13,9],straightforward:[5,6,9],fals:[4,9,13,5,7],on_messag:[12,3],parti:1,fall:12,this_us:7,appar:5,relev:[4,5,7,9,10,13],cool:[8,12],hous:10,list:[0,2,4,5,7,9,11,13],"try":[13,7],item:13,quick:[0,1,10,6],tru:4,round:4,zip:10,pleas:5,shoulod:10,natur:12,direct:[8,5,7],across:[4,2],second:5,design:[4,7,6],pass:[12,3,5,9],download:10,bake:1,port:[10,5,7],compat:6,index:1,what:[0,1,5,7,9,10,12,13],this_field:13,sub:0,section:[4,10],abl:[10,12,7],invok:10,current:[4,12,5,6,7],delet:[13,5,7],"_get_valu":13,last_login:4,modelprototyp:[13,5,7],helloworldapp:[0,10],"new":[1,4,5,6,7,10,12,13],ascii:4,appeal:5,method:[4,13,5,6],whatev:12,full:[13,6],gener:[4,3],here:[0,3,5,10,12,13],behaviour:[11,13],met:13,mojosockethandl:[12,3],coerc:13,logout:9,address:4,path:[10,7],becom:5,modifi:0,valu:[4,13,5,6,9],login_assist:[4,6,9],search:1,base_interfac:7,mojo_set:8,convers:12,multiplex:[11,12],on_clos:3,datetim:[13,5],base:[0,1,3,4,7,6,10,13],make_random_password:4,another_field:13,chang:[0,4,5,7,9,10,13],control:5,via:[12,7,6],to_delet:13,extra:5,appli:4,app:[0,1,2,5,10,11,12],prefer:6,is_authent:[4,9],schemaless:13,api:1,visibl:5,instal:[4,1,10,7],redi:5,coercion:13,unit:10,mongo:[4,13],regex:2,from:[0,1,2,3,4,5,6,7,9,10,12,13],describ:7,would:[0,12,13,5],commun:12,distinct:5,intiti:12,regist:12,two:[3,5,6,7,9,12,13],date_join:4,next:[6,9],sessionobj:4,find_one_async:[13,5,7],call:[2,3,4,5,7,12,13],usr:10,recommend:[0,10,12,7],msg:[12,3],simpler:3,type:[0,1,10,13,5],start:[0,1,2,5,8,10,11,12],minor:7,more:[2,4,5,8,10,11,12,13],to_insert:13,relat:5,site:[10,3,9],function_nam:7,flag:4,indic:[4,1],hold:[5,6],basesockethandl:[12,3],must:13,none:[3,4,7,6,8,9,13],endpoint:3,join:[4,12],hour:4,socketio:[1,12,11],alia:13,setup:[10,1,12,3,7],work:[0,2,5,6,9,10,12],tag_nam:5,tag:5,can:[1,2,3,4,5,7,8,10,11,12,13],sessionmixin_sync:[8,6,9],purpos:[13,6],root:10,blogpost:5,def:[0,3,5,6,7,8,9,12,13],appropri:[4,10,7],overrid:[13,3,7,6,9],heart:5,"_is_session_valid":4,favourit:[10,5],quickstart:[10,1],objectid:[4,13,5],give:[10,8],process:[4,5],insert_async:13,lightweight:1,templat:[0,1,5,6,7,9,10,11],minimum:13,want:[4,5,8,10,12,13],onlin:3,keep:10,blog_app:10,multipl:[4,13],secur:[4,12,6],anoth:[4,10,3],snippet:7,how:[4,2,5],anyon:5,instead:[8,7,6],simpl:[13,3,5,6],this_session_valu:6,map:[0,11,2,13],overridden:13,mojo_blog:10,after:4,variant:13,appnam:11,mac:10,mixin:[1,4,6,8,9,12],router:10,mai:10,end:[13,7],mak:0,associ:7,handl:[0,11,12,5],bakend:[],essenti:[4,7],third:1,tutori:10,classmethod:13,explicit:13,validate_is_nul:13,django:[1,5],callback:[5,6],maintain:4,allow:[4,13],enter:10,first:[0,1,5,6,7,10],order:[4,7],includ:[1,13,7],belong:4,help:[4,1,12,5],allow_empti:[13,5],over:5,move:[2,5],soon:5,"abstract":7,familli:6,through:[4,8,7],affect:10,flexibl:1,mainli:[4,13],whatever_field:13,paramet:[4,13,5,7],write:[0,1,5,7],style:[13,5,6,7],group:[4,10,2,5],directli:[4,10,12,13,5],nifti:6,chosen:[4,13],cla:0,strang:10,session_key_valu:9,window:[0,10],mynewproject:10,requir:[0,3,4,5,10,13],mytestmodel:13,persist:[4,6],bin:10,decod:4,depopul:3,main:[4,10,13,5,6],might:[11,9],alter:1,finer:13,non:[4,13,5,6,7],good:5,"return":[4,5,6,7,9,13],thei:[0,2,5,6,8,10,13],python:[0,10,12,5,11],auto:11,safe:7,dai:4,auth:[1,3,4,7,6,9],easiewr:5,"break":10,framework:[1,3,4,5,12,13],db_name:7,funciton:[6,9],now:[0,12,13,5],introduct:[],name:[4,12,5,7],anyth:5,edit:12,drop:5,authent:[4,1,6,9],separ:11,easili:[10,5,7],editor:10,each:[5,6,10,11,12,13],debug:[0,1,10],fulli:[0,10,7,6],unicod:13,updat:5,side:12,mean:13,individu:10,realli:5,heavi:5,contributor:5,"static":10,expect:[13,7],mojo_manag:[10,11],veri:[1,5],our:[13,5],event:[12,3],out:[0,4,5,10,11,13],variabl:[8,12,13,6],ictionari:[],shown:13,accomplish:[4,10,5],typecast:13,influenc:[1,5],open:10,develop:[0,1,5,7,8,11],mojo:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],content:1,rewrit:7,reader:0,print:[13,5,7],intro:[],correct:13,integr:[4,1,13,7,9],assist:[6,9],urlpattern:[0,2],navig:[0,10],written:[12,5,7],manipul:4,standard:[0,2,3,6,8,13],cooki:[4,12,3,6,9],reason:7,orm:[1,13,5,6,9],dictionari:[13,12,3,5,7],alongsid:[4,6,9],org:0,decompress:10,basi:1,projct:10,perform:[4,5],convent:1,befor:[13,5],get_session_cooki:4,where:[0,10,11],could:[0,12],omit:13,synchron:[4,5,6],taht:5,static_url:10,initialis:[4,5,6],datetimefield:[4,13,5],thing:[4,13],length:13,enforc:5,organis:5,outsid:12,retain:7,my_data:13,principl:12,assign:[13,5,6,7],new_minimal_post:5,oper:[13,5,6],render:[0,5,6,7,8,9,12],feel:5,onc:[4,10],independ:10,yourself:12,date:[4,10],unlik:13,alreadi:[0,6,9],done:10,wrapper:[7,6],blank:4,installed_app:[0,10],miss:5,datastor:5,hood:13,new_password:4,differ:[10,13,5,7],acquaint:1,projectnam:10,stamdard:5,data:[1,3,4,5,6,7,9,12,13],top:12,linenothreshold:[],system:[4,1],least:7,found:10,max_length:13,similarli:6,logged_in:[4,12,3,6],conveni:3,easier:[4,8,5,9],store:[0,3,4,5,6,9,13],schema:[5,7],adher:7,option:[4,13],asyncmongo:7,namespac:13,tool:[4,5,7],sync:9,broadcast:[12,3],sraightforward:7,part:[4,5,6,7,9,12,13],accompani:4,"_logout":4,termin:10,attempt:5,than:13,png:10,gloabl:10,serv:[8,11],target:[6,9],provid:[4,6,9],remov:[4,13],requesthandl:[0,1,2,4,6,8,9,11,12],logout_assist:4,structur:[10,1,13,5],charact:[4,13],project:[0,1,2,5,7,8,10,11,12],expiry_dai:4,mojohandl:[0,8,12,6,9],minut:4,typic:10,treanslat:7,seri:[4,10,5],pre:5,save_async:13,fieldprototyp:[13,5],validate_max_length:13,"_async":[5,7],ani:[4,5,6,7,8,12],find_on:[4,5,6,7,9,13],raw:13,expir:4,have:[0,1,5,6,7,10,12,13],tabl:[10,1],need:[0,1,4,8,10,13],seen:5,dedic:11,is_member_of:4,objectmapp:[1,13,5,7],sessioninterfac:7,strength:12,engin:[5,6,7],built:[10,13],thisus:[4,13,6,9],inform:[4,7,6],self:[0,3,4,5,6,7,8,9,12,13],client:[12,3],note:[0,10,13,5],mix:[4,2],discret:10,take:[4,5,6,7,10,13],which:[11,13,7,6,9],bcrypt:[4,10],singl:[2,13,5],uppercas:4,ioloop:10,sure:[0,10,5,7],distribut:10,integerfield:13,get_current_us:[4,6,9],tornado:[0,1,2,4,5,6,7,8,9,10,12],"504e0439a9ee2f04a0835a92":4,subtyp:13,your_app_nam:11,most:[0,12,5],regular:[7,6,9],automodul:[],deploi:10,"class":[0,3,4,5,6,7,8,9,11,12,13],tradit:[5,7],urg:5,don:[1,8],url:[0,1,2,8,10,11],"_return_model_object":7,request:[0,3,4,5,6,8,9,10,11,12],wtform:[10,1],doe:[4,12,9],declar:8,place:[0,10],determin:4,pattern:2,"_id":[4,5],dot:[13,5],max_valu:13,embeddedmodelfield:13,text:13,"__str__":13,random:4,new_sess:4,session:[1,3,4,7,6,8,9,10,12],get_session_kei:[6,9],"_login":[4,9],fine:13,find:[1,13,5,7],redirect:[6,9],access:[0,5,6,7,8,10,13],onli:[4,12,3,5,7],explicitli:5,locat:10,configur:12,activ:[4,12,5],state:4,should:[0,4,5,6,10,12,13],version:[0,5],dict:[4,13,5,9],folder:[10,11,12],local:0,hope:5,meant:4,info:10,hit:4,min_valu:13,variou:[10,5],get:[0,1,4,5,6,7,8,9,10,11,12,13],familiar:[1,5],jsonobj:12,sesionmanag:4,becaus:5,return_dict:7,cannot:4,"_set_session_kei":4,report:5,joinedstatu:12,restart:0,remove_from_group:4,mapper:[13,7],enabl:[1,3,7,6,12,13],yield:[13,5,6,7],"public":0,stuff:8,common:[3,6],contain:[10,2,13],sessionmodel:9,delete_async:13,view:[0,1,10,2,11],set:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],dump:12,creator:7,on_open:3,maximum:13,model_inst:13,see:[0,1,2,4,6,9,10,13],syncron:9,arg:[0,12,13,7,6],fail:[6,9],close:7,dtd:0,retriev:13,setup_sess:4,statu:[4,3],still:5,lack:5,databas:[1,4,5,6,7,8,9,10,11,13],someth:[10,12],tend:7,enough:[10,7],"_get_session_kei":4,"import":[0,2,3,4,5,6,9,10,12,13],awai:[10,7],email:4,app1socket:12,ui_modul:[10,11],kei:[1,3,4,5,6,11],sole:9,conjunct:4,nbame:10,entir:13,html4:0,len:13,objectidfield:[13,5],find_async:13,come:[13,6,9],embed:[4,13,5],"__unicode__":13,get_valu:13,both:[12,9,5,7],last:4,easi:[1,4,5,6,7,13],session_model:[4,6],admin:[6,9],similar:[12,5,7],howev:[10,12],against:[4,5],groupobj:4,etc:7,instanc:[13,5],grain:13,context:6,logic:[0,13],let:[10,13,9],eth:10,whole:6,load:[10,6],equesthandl:0,simpli:[0,5,6,9,10,12],point:8,instanti:[13,5],highlight:[],format:[0,5,7],arriv:12,chmod:10,"__class__":13,shortcut:4,suppli:6,socketconnectionhandl:[12,3],websocket:12,url_pattern:2,assum:[5,9],backend:[1,9,5,6,7],flooat:[],user_id:3,evalu:13,is_superus:4,sessionmixin_async:[7,6],due:5,been:13,json:[4,12],much:3,interpret:0,basic:[0,8,13,7,9],popul:[1,3],valueerror:13,somwth:0,field:[4,1,13,5],life:8,imag:10,expiry_hour:4,gen:[13,5,6,7],floatfield:13,valididti:4,togeth:13,input:[4,13,5,7],those:[12,5],implement:[1,5,6,7,9,12,13],"case":[4,6],tempalt:0,look:[10,5,9],get_argu:[6,9],packag:[10,12],properti:[8,13,5,6,7],kwarg:[0,7,6,8,12,13],batch:13,valud:4,defin:[11,13,5],"while":[4,5,7],post_intro:5,neat:5,outcom:4,abov:[0,12,13,5,7],error:[0,8,10,6,9],login:[4,8,6,9],modul:[1,3,4,5,6,7,10,12],loos:0,real:5,sessionmixin:[0,1,4,6,8,9],create_new_sess:6,chat:[12,3],helper:[1,4,6,9,10,11],readi:[4,10],them:[0,4,13,5],attribut:[4,9],itself:6,"50571e5f3d941cdc4487bdf1":5,test_valu:6,seem:5,"__init__":13,asyncmongobackend:[5,7],parent:13,"null":13,present:9,welcom:10,prior:5,receiv:12,alphabet:4,make:[0,1,3,4,5,6,7,8,9,10,11,12],couchdb:5,same:[0,4,2,13,5],check:[0,3,4,6,9,13],member:[4,12],date_publish:5,html:[0,5,6,7,8,9,12],interact:[12,7],authmanag:[4,1],set_session_kei:[6,9],document:[0,2,4,7,12,13],complet:[0,5],wrap:6,overal:12,http:[0,10],referenc:[10,7],nest:13,mang:5,driver:[4,8,5,6,7],loginhandl:[6,9],solut:13,sessionmanag:[4,6,9],capabl:0,rais:13,thispost:5,user:[3,4,7,6,9,10,12,13],mani:[8,7],respons:12,tradition:13,expand:[8,13],lib:10,task:[13,3,5,6,7],off:[4,1],machineri:6,eleg:11,entri:2,well:[13,5],inherit:[13,9],without:[1,2,5,6,7,10,13],set_cooki:9,exampl:[4,5,6,7,12,13],command:[0,10,12],thi:[0,2,3,4,5,6,7,8,10,11,12,13],model:[1,4,5,6,7,9,10,11,13],mojoauthmixin:[4,8,7,6,9],rout:[0,1,2],validate_typ:13,identifi:[12,6],just:[0,12,5,7],less:5,when:[0,2,4,5,10,11,12,13],modular:1,rule:13,userobj:4,insid:0,"5059fb6b3d941cdc4487bdff":5,aspect:5,heavili:1,flavor:9,speed:0,resport:5,web:[10,9,5,6,7],password:[4,6,9],curent_us:4,expos:[3,5,6,7,9,13],also:[0,4,13,6],set_password:4,shoul:4,get_session_object:6,usernam:[4,13,7,6,9],littl:13,blog:5,"_create_new_sess":[4,6],add:[0,1,4,5,7,9,13],valid:[4,12,13,5],your_db_nam:5,inner:12,mojosessionmixin:12,embeddedfield:13,extend:[4,1,13],har:7,save:[0,4,5,6,7,9,10,13],transit:0,match:4,build:1,earli:5,applic:[0,5,6,8,9,10,11],request_handl:4,around:[13,7,6],transpar:[12,5],read:[12,5],app2socket:12,know:12,burden:5,step:10,amp:10,bit:[7,9],loader:11,recurs:13,python2:10,linux:10,insert:[13,5,7],"_setup_connect":7,like:[0,5,9,10,12,13],success:4,reset_sess:4,signal:3,manual:6,integ:13,server:[0,2,7,8,10,11,12],collect:[11,13,6],benefit:5,paramat:[4,13],either:[4,12,6],martin:7,async:[5,9],is_async:7,manag:[1,3,4,6,8,9,10,12],underli:13,www:0,login_assit:4,"_db":[8,7],creation:1,some:[1,3,5,8,9,12,13],back:[13,7,6,9],intern:[4,13],logged_in_sess:[12,3],librari:4,add_to_group:4,virtualenv:10,guid:1,listfield:[4,13,5],channel:[11,12],leak:6,avoid:4,normal:0,definit:[4,10,2,13],subclass:[0,3,5,6,7,8,9,13],save_session_object:6,exisitng:4,behav:[0,13,5],speak:12,localhost:[0,10],refer:8,encourag:5,object:[0,2,4,5,6,7,8,9,12,13],run:[0,10,13,5],quit:[5,9],"_encode_sess":4,usag:[4,13,3,7,6],requestmanag:9,els:[4,13,6,9],collection_nam:7,host:[5,7],authmixin:[0,1,12,9],although:12,output:[1,13],"__name__":13,post:[5,6,9],"super":[4,13],slug:5,handi:[8,12],expiri:4,sbin:10,modularis:11,actual:0,socket:[11,12,3],world:[13,6],bahva:[],slightli:0,page:[0,1,2,5,6,9,10],degre:5,lifecycl:5,messag:[12,3],commit:13,produc:13,block:[4,13,7,6],tornadio2:[10,1,12,3],own:[1,4,7,11,12,13],logo:10,"float":13,encod:[4,6,9],bound:13,automat:[0,2,3,4,6,10,12],three:4,down:[10,7],empti:[13,5],expiry_minut:4,ensur:[2,5,6,7,10,13],bson:[13,5],storag:13,your:[0,1,2,3,5,6,7,8,9,10,11,12,13],w3c:0,log:[4,12,3,6,9],wai:[0,2,5,6,10,13],area:10,lok:0,support:[0,1,5,7,10,12],bodi:0,"long":[4,5],custom:13,avail:[0,2,3,5,6,7,9,10],strict:13,handler:[0,8,10,11],interfac:7,prettier:[0,1],lot:8,troubl:13,strictli:13,uder:4,stage:5,asset:10,"function":[1,2,4,5,6,7,8,9,10,11,12,13],head:0,doctyp:0,delete_bulk_async:13,form:[1,13,11],offer:[10,13,7,6],forc:7,tupl:2,bundl:12,criteria:5,serverhelp:[],shorter:13,thji:5,line:[0,10,5],"true":[0,4,13,5,9],bug:5,congratul:10,reset:4,concaten:2,"throw":13,made:[10,3],flavour:[6,9],evolut:5,consist:[4,13,5,6],possibl:[0,13,9],"default":[1,4,5,6,11,12,13],notat:5,app2:12,app1:12,asynchron:[4,5,6,7,12,13],below:5,opein:10,socket_handl:[11,12],otherwis:5,subcla:0,booleanfield:[4,13,5],emit:[12,3],connect:[12,3,7],som:13,socketconnect:3,featur:[1,6],uid:6,creat:[0,4,7,6,10,11,13],sesison:[4,6,9],"int":13,certain:[11,5],dure:7,doesn:4,repres:[4,13,5],current_sess:[12,3],sockethandl:[10,1,12,3],exist:[4,13],session_id:[4,12,3,6],file:[0,2,5,7,8,10,11,12],"_is_logged_in":4,pip:7,ship:7,myrequesthandl:[2,5],keynam:9,again:4,encrypt:[4,12],googl:5,new_model_inst:13,titl:[0,5],boot:7,detail:2,new_valu:6,session_valu:6,"_decode_sess":4,other:[10,1,13,7],bool:13,rememb:3,newpost:5,test:[10,7],ignor:5,you:[0,1,2,3,4,5,7,8,9,10,11,12,13],pymongo:[13,5,7],roll:[1,12],mongodb:[13,5,7],why:[1,5,9],asyncmongo_backend:[5,7],stringfield:[13,5],thishandl:7,scale:1,track:[4,1,12],establish:13,throughout:13,delete_bulk:[13,5],vein:12,session_data:4,bulk:5,bitbucket:5,asyncron:9,directori:[0,10,5],remit:12,post_bodi:5,klass:13,time:[4,1,10],mihjgt:11,tornadio:[10,12],hello:[0,12,2,13,6],pagehandl:8,prototyp:7},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:method","4":"py:attribute","5":"py:classmethod"},titles:["Mojo Views","Mojo - a framework for Tornado","Routing pages with URL&#8217;s","Mojo.SocketHandlers","Mojo.Auth","The Mojo ORM and Models","Mojo.Auth.Mixins","Mojo.Backends","Mojo.RequestHandlers","Using Mojo&#8217;s Auth and Session Mixins","Quickstart: Using Mojo for the first time","Mojo Apps","Mojo and SocketIO","Mojo.ObjectMapper"],objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","method","Python method"],"4":["py","attribute","Python attribute"],"5":["py","classmethod","Python class method"]},filenames:["docs/views","index","docs/urls","docs/api/SocketHandlers","docs/api/Auth","docs/models","docs/api/Mixins","docs/api/Backends","docs/api/RequestHandlers","docs/authentication","docs/quickstart","docs/apps","docs/socketio","docs/api/ObjectMapper"]})
View
90 Documentation/docs/authentication.rst
@@ -1,3 +1,89 @@
-Using Mojo's Auth module
-========================
+Using Mojo's Auth and Session Mixins
+====================================
+
+To make Tornado a bit easier to use and integrate with your application, Mojo provides a sesison management mixin that
+adds database-backed sessions to your requests.
+
+The Session Mixin assumes that a database backend and ORM is present, which is why it comes in both sync and async flavors.
+The AuthMixin does not assume that a database is present and solely uses the set_cookie functionality of Tornado to make
+the get_current_user functionality work.
+
+AuthMixin
+---------
+
+The AuthMixin basically overrides get_current_user() in the MojoRequestHandler and adds a SessionManager object to the
+attributes of the RequestHandler. Using the SessionManager, it is possible to login/logout the user::
+
+ if thisUser is not None:
+ if is_authenticated:
+ SessionManager(request)._login(thisUser) #Will make the relevant changes to the cookies.
+ return True
+ else:
+ return False
+ else:
+ return False
+
+Using it in a request might look like::
+
+ import tornado.web
+ from Mojo.RequestHandlers.MojoHandler import MojoRequestHandler
+ from Mojo.Auth.Mixins.MojoAuthMixin import MojoAuthMixin
+ from Mojo.Auth.models import User
+ from Mojo.Auth.Helpers import login_assistant
+
+ #To implement the mixin, simply subclass it alongside the regular MojoRequestHandler and the authentication
+ #funcitonality will be come available.
+
+ class loginHandler(MojoRequestHandler, MojoAuthMixin):
+
+ def get(self):
+ #Override the get function to render the page, check current_user to see if we're already logged in
+ if self.current_user:
+ self.render('login.html', error='ALREADY LOGGED IN')
+ else:
+ self.render('login.html', error=None)
+
+ def post(self):
+ #Get the username and password from the request
+ username = self.get_argument('username')
+ password = self.get_argument('password')
+
+ target = self.get_argument('next', '/admin/')
+
+ #Get the user from the database
+ thisUser = User.find_one({'username':username})
+
+ #Log the user in using the login assistant
+ if login_assistant(thisUser, password, self):
+ self.redirect(target)
+ else:
+ self.render('login.html', error='Login failed')
+
+The SessionMixin
+----------------
+
+The SessionMixin comes in two flavours: Syncronous and Asyncronous, depending on what backend is being used in Mojo.
+To implement the SessionMixin, simply add it to the inheritance list as part of your RequestManager::
+
+ from Mojo.Auth.Mixins.SessionMixins import SessionMixin_Sync
+ class loginHandler(MojoRequestHandler, SessionMixin_Sync):
+
+ def get(self):
+ pass
+
+The SessionMixin exposes some basic functionality that will let you get and set session data as part of your site and save
+it to the database.
+
+All session data is stored in the SessionModel as a Base64 encoded string that is a ``dict``. To get and set session
+values is quite straightforward::
+
+ from Mojo.Auth.Mixins.SessionMixins import SessionMixin_Sync
+ class loginHandler(MojoRequestHandler, SessionMixin_Sync):
+