Here are things for Django developers to know about oTree.
otree command is a customized version of Django’s
otree runserver is basically equivalent to
python manage.py runserver.
In addition to the built-in Django management commands like
oTree defines a few extra ones like
For the list of available commands, enter
For information about a specific command, enter
otree help [command], e.g.
otree help test.
Migrations and “resetdb”¶
If you are using oTree, you generally shouldn’t use
We are not fully compatible with migrations yet.
otree resetdb, which will reset and sync the database.
The folder containing your games is a Django project, as explained here.
It comes pre-configured with all the files, settings and dependencies so that it works right away. You should create your apps inside this folder.
oTree doesn’t work with Gunicorn, mod_wsgi, or any other typical WSGI server.
Because it uses Django Channels
for WebSocket support, it should be run with
which internally starts the Daphne server, several channels workers, and a task queue.
More info here.
Auto-save of models¶
In oTree, you don’t need to explicitly call
.save() on your models;
oTree will do it automatically (it uses an idmap cache).
However, this auto-save feature does not apply to custom models or views that don’t inherit from oTree’s,
or custom WebSocket/AJAX code. In that case, you have to remember to save your database
models yourself as you would in a regular Django project.
You will also need to figure out how to query your models using Django’s ORM and the model’s pk/code, etc.
Misc notes on models¶
default=Noneare not necessary in your model field declarations; in oTree fields are null by default.
initialis an alias for
defaultin a model field’s kwargs.
max_lengthis not required.
Adding custom views & URLs¶
First, define the view function in one of your project modules. It can be a function-based view or class-based view.
# In my_app.views from django.http import HttpResponse def my_view(request): return HttpResponse('This is a custom view')
Create a file
urls.py in your project root.
In this file, put:
# urls.py from django.conf.urls import url from otree.urls import urlpatterns urlpatterns.append(url(r'^my_view/$', 'my_app.views.my_view'))
In your settings.py, set
ROOT_URLCONF to point to the
urls.py that you just created:
# settings.py ROOT_URLCONF = 'urls'
If you need to access oTree’s models, you will have to handle querying and saving objects yourself.
Real-time and WebSockets¶
oTree uses Django channels for real-time (WebSocket) functionality.
If you are comfortable with more advanced programming, you can add your own real-time interactions such as a continuous-time market.
First, create a module
consumers.py in one of your apps.
For each WebSocket,
you should create a
connect consumer and
Here we will use a trivial example, taken from the Channels “getting started”
# In consumers.py from channels import Group # Connected to websocket.connect def ws_add(message): Group("chat").add(message.reply_channel) # Connected to websocket.disconnect def ws_disconnect(message): Group("chat").discard(message.reply_channel)
oTree is still using channels v 0.17.3, which has some incompatibilities with the latest version. See here.
Next, create a module
routing.py (either in your project root or in an app)
and append your routes to oTree’s built-in routes:
from channels.routing import route from myapp.consumers import ws_add, ws_disconnect from otree.channels.routing import channel_routing channel_routing += [ route("websocket.connect", ws_add, path=r"^/chat"), route("websocket.disconnect", ws_disconnect, path=r"^/chat"), ]
In settings.py, set
CHANNEL_ROUTING = 'routing.channel_routing'
(this is the dotted path to your
channel_routing variable in