不要怂,就是干,撸起袖子干!

Commit 07e9c9e4 by Jan Aagaard Meier

RTD migration

1 parent 02f7cf26
<script type="text/javascript">
fromGithub = function (partialId, ext) {
ext = ext || '';
var $partial = $("#" + partialId)
$.get("https://cdn.rawgit.com/sequelize/express-example/master/" + partialId.replace("_", "/") + ext, function (code) {
if (ext === '.js') {
code = hljs.highlight('js', code).value;
}
code = '<div class="highlight"><pre>' + code + '</pre></div>';
$partial.replaceWith(code);
}, 'html');
}
</script>
## Introduction
This article explains the usage of Sequelize with the MVC framework Express.You will learn how and where to define models and how to load them when needed.
## A minimal express application
In order to create a minimal express application, we need to install express first and scaffold a project. We can do this via the following commands:
```bash
$ mkdir example-app
$ cd example-app
$ npm install express express-generator
$ node_modules/.bin/express . -f
$ npm install
$ ./bin/www
```
You should now be able to see a tiny welcome page on `http://localhost:3000`
## Adding Sequelize to the application
Now that we have the express application in place, we can start adding Sequelize to it. What we need for that are the following packages: sequelize, sequelize-cli, sqlite3. Please note, that for the sake of simplicity this tutorial will use SQLite.
```bash
$ npm install --save sequelize@2.0.0-rc1 sequelize-cli sqlite3
```
This will install the respective packages and uses the upcoming major release of sequelize. We can now let the sequelize CLI initialize the project's directory:
```bash
$ node_modules/.bin/sequelize init
```
Running this command will create the folders `config`, `migrations` and `models`.
## Implementing a todo app
As an example application we will create a very basic and simple todo tool, which allows the creation of users and the management of their tasks.
### bin/www
In order to create a maintainable application, we will put all the database logic into the `models` folder. When the application gets fired up, sequelize will sync the models with the database and afterwards start the server. This way we don't clutter the application while making use of sequelize's features.
<div id="bin_www"></div>
<script>$(function () { fromGithub("bin_www") })</script>
### models/index.js
This file has been generated with the sequelize CLI and collects all the models from the `models` directory and associates them if needed.
<div id="models_index"></div>
<script>$(function () { fromGithub("models_index", '.js') })</script>
### models/user.js
All models of our application are located as separate files in the `models` folder. If you want to add a new model, just add it to this folder and everything will work automagically. Also you can use the sequelize CLI's `sequelize model:create`.
**Notice** that the `associate` method receives a parameter `models`, which contains every declared model within the models directory.
<div id="models_user"></div>
<script>$(function () { fromGithub("models_user", '.js') })</script>
### models/task.js
The other needed model is `Task`. It relates to the `User`.
<div id="models_task"></div>
<script>$(function () { fromGithub("models_task", '.js') })</script>
### routes/index.js
The file `routes/index.js` contains the logic for a request against the main homepage. It loads the models module and uses it to load all the users and tasks from the database.
<div id="routes_index"></div>
<script>$(function () { fromGithub("routes_index", '.js') })</script>
This will allow us to iterate over the users in the view file. We will skip the rest of the route files for this article.
### views/index.jade
As we passed the users to the view and include the tasks for each user, we can access the data in the view's template file. Besides listing the users and tasks, there are also forms for creating new instances.
<div id="views_index"></div>
<script>$(function () { fromGithub("views_index", '.jade') })</script>
## What's next?
This article shows a basic approach of how to integrate Sequelize into an ExpressJS application. It allows the very easy management of models by adding new files to a specific folder. Starting the application will automatically sync the schema with the database.
If you don't want to have automatic schema synchronization and instead want migrations, just add a respective step to your deployment script. When you use the CLI for the model generation, you will gain the migration scripts for free as well.
You can find the complete application code [on Github](https://github.com/sequelize/express-example). Feel free to add pull requests to it.
Besides the use of Sequelize as model backend in your ExpressJS application, you might also want to turn your server into a restful API. If that is the case, check out [the repository on Github](https://github.com/sequelize/sequelize-restful)
\ No newline at end of file
## Introduction
This article explains the basic concepts of Sequelize. You will learn how to use the supported dialects, which ways of database setup approaches are available and how common scenarios can be achieved.
## Premise
We will skip the very basic things and directly dive into the Sequelize related stuff. Here is a list of things that have to be in place before you can start:
* Node.JS at v0.8 or higher
* One of the supported databases / SQLite bindings
* The credentials for the respective database
* A basic understanding of how databases are working
* Optional but recommended: Coffee :)
## A word about promises
TODO - a link to bluebird + general promise syntax + catch / error handling
## Setting up a project
Now that your computer is prepared and your coffee sits next to your keyboard,
we can finally get started. First things first: Create a directory and initializeit with NPM!
```bash
$ mkdir my-project
$ cd my-project
$ npm init
```
NPM will ask you a couple of questions. Answer them or just hit the return key until it's satisfied.
Once done, you can install Sequelize and the connector for your database of choice.
```bash
$ npm install --save sequelize
$ npm install --save pg # for postgres
$ npm install --save mysql # for mysql
$ npm install --save sqlite3 # for sqlite
$ npm install --save mariasql # for mariasql
```
## Connecting to the database
Open the created directory in your favorite text editor and add a new file called `app.js` with the following content.
```js
var Sequelize = require('sequelize')
, sequelize = new Sequelize('database_name', 'username', 'password', {
dialect: "mysql", // or 'sqlite', 'postgres', 'mariadb'
port: 3306, // or 5432 (for postgres)
});
sequelize
.authenticate()
.then(function(err) {
console.log('Connection has been established successfully.');
}, function (err) {
console.log('Unable to connect to the database:', err);
});
```
## Managing the schema of your database
Sequelize supports two way of schema management. You can either define so called migrations, which are programmatically changing your database's structure. Or you can let Sequelize create the tables for you.
While the first possibility of using `migrations` takes more time to setup, it's most likely the way to go, if you want to deploy your application on many different server environments. The reason for that is based on the fact, that migrations are consistently changing your database according to the current state of the schema.
However, the automated way of using Sequelize's function `sequelize.sync` will probably be a good choice on your local machine or if you just want to quickly spin up a prototype.
As this article is for beginners, we will skip migrations for now and take a closer look at the automated way.
### Defining a model
In order to let Sequelize create a schemas in the database, you need to describe, what kind of data you want to store. This can be done with `sequelize.define`:
```js
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
});
```
This will define a user model that has a username and password. Furthermore, Sequelize will automatically add the columns `id`, `createdAt` and `updatedAt`. `createdAt` and `updatedAt` are controlled by sequelize - when you `create` a model through sequelize `createdAt` will be set, and whenever you call `updateAttributes` / `save` on a model, `updatedAt` will be set.
### Synchronizing the schema
As we want to store data in the database, we need to create a representation of the model.
```js
sequelize
.sync({ force: true })
.then(function(err) {
console.log('It worked!');
}, function (err) {
console.log('An error occurred while creating the table:', err);
});
```
Once executed, the database will contain a table `Users` (note the plural) with the columns:
* id - INT(11)
* username - VARCHAR(255)
* password - VARCHAR(255)
* createdAt - DATETIME
* updatedAt - DATETIME
Please note, that `{ force: true }` will drop the `Users` table and re-create it.
### Configuration
You might not need the timestamps or you might not want the plural of the model's name as table name, right? Luckily there are configuration possibilities for that.
```js
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
}, {
tableName: 'my_user_table', // this will define the table's name
timestamps: false // this will deactivate the timestamp columns
})
```
And just in case you want to customize the timestamp field names, you can do it like this:
```js
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
}, {
updatedAt: 'last_update',
createdAt: 'date_of_creation'
})
```
Furthermore you can introduce a `deletedAt` timestamp so models are not actually deleted when you call `destroy`. Adding a `deletedAt` timestamp is called making the model 'paranoid':
```js
var User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
}, {
paranoid: true
});
```
## Creating and persisting instances
Sequelize allows the creation of instances in two ways. You can either `build` an object and `save` it afterwards. Or you can directly `create` an instance in the database:
```js
var user = User.build({
username: 'john-doe',
password: generatePasswordHash('i-am-so-great')
})
user.save().then(function() {
/* ... */
})
```
This persists the instance in a two step way. If you want to do everything at once, use the following approach:
```js
User.create({
username: 'john-doe',
password: generatePasswordHash('i-am-so-great')
}).then(function(user) {
/* ... */
})
```
## Reading data from the database
Every defined model has finder methods, with which you can read the database. Searching for a single item can be done with `Model.find`. Retrieval of multiple items needs the use of `Model.findAll`.
```js
User
.find({ where: { username: 'john-doe' } })
.then(function(err, johnDoe) {
if (!johnDoe) {
console.log('No user with the username "john-doe" has been found.');
} else {
console.log('Hello ' + johnDoe.username + '!');
console.log('All attributes of john:', johnDoe.get());
}
});
```
Please note that there won't be any error if no user with the name "john-doe" has been found. This is intended, as there is not internal or authentication error.
## Defining associations
A very common use case is the definition of associations between two or even more models. Once declared, Sequelize will know how to query the database to get or set associated data. Furthermore it will be able to automatically create the respective foreign key columns for you.
Before taking a closer look at the code, it is critical to understand some details about the three different association types.
### One to one
An association between one source and one target is called "one to one" or 1:1 association. It consists of a source that **has one** target and a target that **belongs to** a source.
Sequelize expects a foreign key in the target's schema. That means that there has to be an attribute respectively a column in the target's table.
```js
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasOne(Target)
Target.belongsTo(Source)
sequelize
.sync({ force: true })
.then(function() {
// Even if we didn't define any foreign key or something else,
// instances of Target will have a column SourceId!
});
```
### One to many
An association between one source and many target is called "one to many" or 1:N association. It consists of a source that **has many** targets and some targets which **belong to** a source.
Sequelize expects a foreign key in the target's schema. That means that there has to be an attribute respectively a column in the target's table.
```js
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasMany(Target)
Target.belongsTo(Source)
sequelize
.sync({ force: true })
.then(function() {
// Even if we didn't define any foreign key or something else,
// instances of Target will have a column SourceId!
})
```
### Many to many
An association between many sources and many targets is called "many to many" or N:M association. It consists of sources which **have many** targets and some targets which **have many** sources.
Sequelize expects a junction table which contains a foreign key to the source table and a foreign key to the target table. A row in the table connects a source with a target.
```js
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {})
Source.hasMany(Target)
Target.hasMany(Source)
sequelize
.sync({ force: true })
.then(function() {
// Even if we didn't define any foreign key or something else,
// Sequelize will create a table SourcesTargets.
})
```
### Getting/Setting associations
Defining associations is nice, but won't give you any advantage if you cannot read or set associations. Of course Sequelize will add respective functions to your models. Depending on the type of association you will find different methods:
```js
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {});
Source.hasOne(Target);
Target.belongsTo(Source);
sequelize.Promise.all([
Source.create({}),
Target.create({})
]).spread(function (source, target) {
// Set the association
return source.setTarget(target).return(source);
}).then(function(source) {
// Get the association
return source.getTarget();
}).then(function(_target) {
console.log(_target.values)
/*
{
id: 1,
createdAt: Sun Dec 08 2013 11:46:42 GMT+0100 (CET),
updatedAt: Sun Dec 08 2013 11:46:42 GMT+0100 (CET),
SourceId: 1
}
*/
});
```
### Clearing associations
Assuming we already defined the models (as in the previous code example) and synced the schema with the database, we can clear the associations like this:
```js
source.setTarget(null).then(function() {
return source.getTarget();
}).then(function(target) {
console.log(target);
});
```
### Adding / removing associations
For 1:N and N:M associations it makes sense to not only set the associations, but also to add or remove associations. Furthermore checking for an association can be handy.
```js
var Source = sequelize.define('Source', {})
, Target = sequelize.define('Target', {});
Source.hasMany(Target);
Target.belongsTo(Source);
return sequelize.Promise.all([
Source.create({}),
Target.create({});
Target.create({}),
]).bind({}).spread(function (source, target1, target2) {
// Set the association
this.source = source;
this.target1 = target1;
this.target2 = target2;
return source.setTargets([target1, target2]);
}).then(function() {
// Get the association
return this.source.getTargets();
}).then(function(targets) {
console.log(targets.length) // = 2
// Remove an association
return this.source.removeTarget(this.target1);
}).then(function() {
return source.getTargets();
}).then(function(targets) {
console.log(targets.length) // = 1
// Check for an association
return this.source.hasTarget(this.target1);
}).then(function(hasTarget) {
console.log(hasTarget) // false
// Adding an association
return this.source.addTarget(this.target1);
}).then(function() {
return this.source.getTargets();
}).then(function(targets) {
console.log(targets.length) // = 2
return this.source.hasTarget(this.target1);
}).then(function(hasTarget) {
console.log(hasTarget) // true
});
```
## A combined example
Now that you know the basics of Sequelize, you might want to see everything in a single program.
```js
var Sequelize = require('sequelize')
, sequelize = new Sequelize('database_name', 'username', 'password')
, User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING
});
sequelize.sync({ force: true }).then(function() {
return User.create({ username: 'john', password: '1111' });
}).then(function(user1) {
return User.find({ username: 'john' })
}).then(function(user2) {
console.log(user2.get()); // Get returns a JSON representation of the user
});
```
## What's next?
As there are some more advanced features in Sequelize which are a bit inappropriate for this article, you can check the following resources for further advice:
* [Migrations][0]
* [Data types][1]
* [Configuration of the model][2]
* [Validations][3]
* [Finders][4]
* [Associations][5]
[0]: /docs/latest/migrations
[1]: /docs/latest/models#data-types
[2]: /docs/latest/models#configuration
[3]: /docs/latest/models#validations
[4]: /docs/latest/models#finders
[5]: /docs/latest/associations
\ No newline at end of file
## Introduction
This section covers the use of Sequelize on Heroku. It will explain how to get started with Heroku and what is necessary to setup a proper environment. We will use MySQL on the development machine and PostgreSQL on the remote servers.
## Getting started with Heroku
Before we can roll out any software on the Heroku cluster, we need to sign up and have to connect our development environment. Here are the most basic steps:
* [Sign up][0] for a Heroku account.
* [Install][1] the Heroku Toolbelt. This tool will let you create applications and is a handy way to configure them on the command line.
* Use the new binary to login. Run the following command on command line:`heroku login`
And that's it. You should now be able to do things like `heroku apps`. This should list all applications you've currently created on the Heroku cluster. If you've just created a new account, this should show you an empty list. [You can get further information about the registration process here][2].
## A minimal express application
In order to create a minimal express application, we need to install express first. We can do this via the following commands:
```bash
$ mkdir example-app
$ cd example-app
$ npm install express
$ node_modules/.bin/express . -f
$ npm install
$ node app.js
```
So now we have a default express application. If you point your browser to `http://localhost:8080`, you will see a tiny page welcoming you.
Next step: Deploy the application to Heroku.
## Deployment to Heroku
First of all, we need to add the right version of Node.JS and NPM to the `package.json`. The file should look similiar to this:
```js
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.1.1",
"jade": "*"
},
"engines": {
"node": "0.8.x",
"npm": "1.1.x"
}
}
```
Now we can create a Heroku application and deploy to it:
```bash
$ echo "web: node app.js" > Procfile
$ echo "node_modules" > .gitignore
$ git init
$ git add .
$ git commit -m "initial commit"
$ heroku create
$ git push heroku master
$ heroku ps:scale web=1
$ heroku open
```
You should now see a browser with the same application as on your local machine.
## Spawning a database on Heroku
In order to get a database on Heroku we can use their CLI. Just run the following command and take a closer look at it's output:
```bash
$ heroku addons:add heroku-postgresql:dev
```
This will result in something like this:
```bash
Adding heroku-postgresql:dev on fast-dusk-7858... done, v5 (free)
Attached as HEROKU_POSTGRESQL_BRONZE_URL
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pgbackups:restore.
Use `heroku addons:docs heroku-postgresql:dev` to view documentation.
```
What we will need is the color (sounds strange right?) of the database. In this case we just created a `bronze` one. That means, that we will have an environment variable `HEROKU_POSTGRESQL_BRONZE_URL` containing the URI of the database.
If you are interested in the URI, you can just run this command:
```bash
$ heroku config:get HEROKU_POSTGRESQL_BRONZE_URL
$ # => postgres://pfforbjhkrletg:aic5oO6Cran1g3hk6mJa5QqNZB@ec2-23-21-91-97.compute-1.amazonaws.com:5432/dek11b2j1g3mfb
```
## Adding Sequelize to the application
The following commands will install `sequelize`, the needed PostgreSQL library as well as the MySQL bindings. Also we will create a folder `models`, that will contain the model definitions.
```bash
$ npm install --save sequelize pg mysql
$ mkdir models
```
### app.js
In order to create a maintainable application, we will put all the database logic into the `models` folder. The application's main file will then just sync the models with the database and run the server. This way we don't clutter the application.
```js
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, db = require('./models');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' === app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
db.sequelize.sync().then(function() {
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
});
```
### models/index.js
The idea of this file is to configure a connection to the database and to collect all model definitions. Once everything is in place we will store the stuff in a singleton. This will make it possible to load the file whenever we need database access without running into issues with duplicated database access.
This file will also differ between the local machine and the Heroku server.
```js
if (!global.hasOwnProperty('db')) {
var Sequelize = require('sequelize')
, sequelize = null
if (process.env.HEROKU_POSTGRESQL_BRONZE_URL) {
// the application is executed on Heroku ... use the postgres database
sequelize = new Sequelize(process.env.HEROKU_POSTGRESQL_BRONZE_URL, {
dialect: 'postgres',
protocol: 'postgres',
port: match[4],
host: match[3],
logging: true //false
})
} else {
// the application is executed on the local machine ... use mysql
sequelize = new Sequelize('example-app-db', 'root', null)
}
global.db = {
Sequelize: Sequelize,
sequelize: sequelize,
User: sequelize.import(__dirname + '/user') 
// add your other models here
}
/*
Associations can be defined here. E.g. like this:
global.db.User.hasMany(global.db.SomethingElse)
*/
}
module.exports = global.db
```
### models/user.js
All the other models of our application will be located as separate files in the `models` folder. We will use the `import`-method of Sequelize to load those files.
```js
module.exports = function(sequelize, DataTypes) {
return sequelize.define("User", {
username: DataTypes.STRING
})
}
```
## Running Migrations
To run migrations on Heroku you must have the following entry in your config/config.json file:
```js
"production": {
"use_env_variable": "DATABASE_URL"
}
```
Which also means you must make sure your Heroku environment has [a promoted database.][3] Then from the command line run
```bash
$ heroku run bash
$ sequelize -m
```
## tl;dr
This article explains a straight-forward but maintainable approach for hosting an express application on Heroku. If you don't want to read all the stuff mentioned, just execute the following stuff and have fun.
```bash
$ mkdir example-app
$ cd example-app
$ npm install express
$ node_modules/.bin/express . -f
$ npm install
$ curl -s https://gist.github.com/sdepold/ced7d2a4a847f38901ef/raw/459c923dd0a14841c932bb95ff3be8a8170bd563/package.json > package.json
$ echo "web: node app.js" > Procfile
$ echo "node_modules" > .gitignore
$ npm install --save sequelize pg mysql
$ mkdir models
$ git init
$ git add .
$ git commit -m "initial commit"
$ heroku create
$ git push heroku master
$ heroku ps:scale web=1
$ heroku addons:add heroku-postgresql:dev
$ curl -s https://gist.github.com/sdepold/ced7d2a4a847f38901ef/raw/6db41e130a8b901cd0843bf52390b7cb11db5f15/app.js > app.js
$ curl -s https://gist.github.com/sdepold/ced7d2a4a847f38901ef/raw/26c5a94d74db4a242464b02aa8e0ae4b3bac6880/models-index.js > models/index.js
$ curl -s https://gist.github.com/sdepold/ced7d2a4a847f38901ef/raw/3b37b0e5d459b2e4b3833a63a018b600a1001795/models-user.js > models/user.js
$ clear
$ # Now run the following command and change HEROKU_POSTGRESQL_BRONZE_URL in
$ # the file "models/index.js" to its result:
$ heroku config|grep HEROKU_POSTGRESQL|cut -d : -f 1
$ git add .
$ git commit -m "sequelize application"
$ git push heroku master
$ heroku open
```
[0]: https://api.heroku.com/signup/devcenter
[1]: https://toolbelt.heroku.com/
[2]: https://devcenter.heroku.com/articles/quickstart
[3]: https://devcenter.heroku.com/articles/heroku-postgresql#establish-primary-db
\ No newline at end of file
table {
width:100%;
}
th:nth-child(1),
td:nth-child(1) {
width: 35%;
word-break: break-all;
}
td:nth-child(2),
td:nth-child(2) {
width: 20%;
word-break: break-word;
}
td,
th {
padding: 6px 13px;
border: 1px solid #ddd;
}
tr:nth-child(2n) {
background-color: #f8f8f8;
}
\ No newline at end of file
"use strict";
var dox = require('dox')
, program = require('commander')
, fs = require('fs')
, path = require('path')
, git = require('git')
, _ = require('lodash');
program
.version('0.0.2')
.option('-f, --file [file]', 'Process a single file', '')
.option('-a, --all', 'Process all files, generate index etc. (default if no options are specified')
.option('-o --out [dir]', '', path.dirname(__filename) + '/api')
.parse(process.argv);
var files;
if (program.file) {
files = [{file: program.file, output: 'tmp'}];
} else {
files = [
{file:'lib/errors.js', output: 'errors'},
{file:'lib/sequelize.js', output: 'sequelize'},
{file:'lib/instance.js', output: 'instance'},
{file:'lib/model.js', output: 'model'},
{file:'lib/hooks.js', output: 'hooks'},
{file:'lib/associations/mixin.js', output: 'associations'},
{file:'lib/promise.js', output: 'promise'},
{file:'lib/transaction.js', output: 'transaction'},
{file:'lib/data-types.js', output: 'datatypes'}
];
}
var Comment = function(data, file) {
this.data = data;
this.file = file;
this.string = '';
};
Comment.prototype.getTag = function(tagName) {
return _.find(this.data.tags, function (tag) {
return tag.type === tagName;
});
};
Comment.prototype.getTags = function(tagName) {
return _.where(this.data.tags, function (tag) {
return tag.type === tagName;
});
};
Comment.prototype.hasTag = function(tagName) {
return this.getTag(tagName) !== undefined;
};
Comment.prototype.getName = function () {
var tag;
tag = this.getTag('name');
if (tag) {
return tag.string;
}
tag = this.getTag('class');
if (tag) {
return tag.string;
}
tag = this.getTag('property');
if (tag) {
return tag.types[0];
}
tag = this.getTag('method');
if (tag) {
return tag.string;
}
return this.data.ctx.name;
};
Comment.prototype.getParams = function () {
if (this.isProperty()) {
return '';
}
// Only show params without a dot in them (dots means attributes of object, so no need to clutter the signature too much)
var params = [] ;
this.getTags('param').forEach(function (paramTag) {
if (paramTag.name.indexOf('.') === -1) {
params.push(paramTag.name);
}
});
return '(' + params.join(', ') + ')';
};
Comment.prototype.isProperty = function () {
return !this.hasTag('method') && this.data.ctx && this.data.ctx.type === 'property';
};
Comment.prototype.putString = function(str) {
this.string += str;
};
Comment.prototype.putLine = function(str) {
str = str || '';
this.putString(str + "\n");
};
Comment.prototype.putLines = function(lines) {
lines.forEach(function (line) {
this.putLine(line);
}, this);
};
Comment.prototype.toString = function () {
return this.string + "\n";
};
['class', 'mixin', 'constructor'].forEach(function (prop) {
Comment.prototype['is' + prop.charAt(0).toUpperCase() + prop.slice(1)] = function () {
return this.hasTag(prop);
};
});
Comment.prototype.githubLink = function() {
return 'https://github.com/sequelize/sequelize/blob/' + Comment.commit + '/' + this.file + '#L' + this.data.codeStart;
};
Comment.concatTypes = function (types, convertEntities) {
if (convertEntities === undefined) {
convertEntities = true;
}
var type = types.join('|');
if (type.indexOf('<') !== -1 && type.indexOf('>') === -1) {
// If the string is Array<something|somethingelse> the closing > disappears...
type += '>';
}
if (convertEntities) {
// Convert a couple of things to their HTML-entities
// The spacing around | is intentional, in order to introduce some linebreaks in the params table
type = type.replace('|', ' &#124; ')
.replace('>', '&gt;')
.replace('<', '&lt;');
}
return type;
};
var parseComments = function (comments, file) {
var output = ''
, comment
, name
, returns
, mixes
, deprecated
, see
, params
, extend
, aliases;
comments.forEach(function (data) {
if (data.tags.length) {
comment = new Comment(data, file);
name = comment.getName();
comment.putLine('<a name="' + name.toLowerCase() + '"></a>');
if (comment.isClass()) {
comment.putLine('# Class ' + name);
} else if (comment.isMixin()) {
comment.putLine('# Mixin ' + name);
} else if (comment.isConstructor()) {
comment.putLine('## `new ' + name + comment.getParams() + '`');
} else {
comment.putString('## `' + name + comment.getParams() + '`');
if (comment.hasTag('return')) {
returns = comment.getTag('return');
var returnType = Comment.concatTypes(returns.types, false); // We don't convert HTML entities since tihs is displayed in a literal block
comment.putString(' -> `' + returnType + '`');
}
comment.putLine();
}
comment.putLine('[View code](' + comment.githubLink() + ')');
comment.putLine(comment.data.description.full);
if ((mixes = comment.getTags('mixes')).length) {
comment.putLine('### Mixes:');
mixes.forEach(function (mixin) {
comment.putLine('* ' + mixin.string);
});
}
if (deprecated = comment.getTag('deprecated')) {
comment.putLine('**Deprecated** ' + deprecated.string);
}
if ((see = comment.getTags('see')).length) {
comment.putLine();
comment.putLine('**See:**');
comment.putLine();
var link;
see.forEach(function (see) {
if (see.local) {
link = see.local.match(/{(.*?(?:|#.*?))}/)[1];
comment.putLine('* [' + link + '](' + link.toLowerCase() + ')');
} else {
comment.putLine('* [' + see.title | see.url + '](' + see.url + ')');
}
});
comment.putLine();
}
if (comment.hasTag('param')) {
params = comment.getTags('param');
comment.putLines([
'',
'**Params:**',
'',
'| Name | Type | Description |',
'| ---- | ---- | ----------- |'
]);
var type;
params.forEach(function (param) {
type = Comment.concatTypes(param.types);
comment.putLine('| ' + param.name + ' | ' + type + ' | ' + param.description + ' |');
});
comment.putLine();
}
if (returns && returns.description) {
comment.putLine('__Returns:__ ' + returns.description);
}
if ((aliases = comment.getTags('alias')).length) {
comment.putLine('__Aliases:__ ' + aliases.map(function (a) {
return a.string;
}).join(', '));
}
if (extend = comment.getTag('extends')) {
comment.putLine();
comment.putLine('__Extends:__ ' + extend.otherClass);
}
comment.putLine();
comment.putLine('***');
output += comment.toString();
}
});
output += '_This document is automatically generated based on source code comments. Please do not edit it directly, as your changes will be ignored. Please write on <a href="irc://irc.freenode.net/#sequelizejs">IRC</a>, open an issue or a create a pull request if you feel something can be improved. For help on how to write source code documentation see [JSDoc](http://usejsdoc.org) and [dox](https://github.com/tj/dox)_';
return output;
};
var code, obj, output, path;
new git.Repo(path.dirname(__filename) + '/..', function (err, repo) {
repo.head(function (err, status) {
Comment.commit = status.commit;
files.forEach(function (file) {
fs.readFile(file.file, function (err, code) {
obj = dox.parseComments(code.toString(), { raw: true});
path = program.out + '/' + file.output + '.md';
console.log(path)
var output = parseComments(obj, file.file);
fs.writeFile(path, output);
});
});
});
});
## Associations
With Sequelize you can also specify associations between multiple classes&period; Doing so will help you to easily access and set those associated objects&period; The library therefore provides for each defined class different methods&comma; which are explained in the following chapters&period;
**Note&colon; **Associations with models that use custom primaryKeys &lpar;so not the field 'id'&rpar; are currently unsupported&period;
### One-To-One associations
One-To-One associations are connecting one source with exactly one target&period; In order to define a proper database schema&comma; Sequelize utilizes the methods`belongsTo`and`hasOne`&period; You can use them as follows&colon;
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
 
// One-way associations
Project.hasOne(User)
 
/*
In this example hasOne will add an attribute ProjectId to the User model!
Furthermore, Project.prototype will gain the methods getUser and setUser according
to the first parameter passed to define. If you have underscore style
enabled, the added attribute will be project_id instead of ProjectId.
 
You can also define the foreign key, e.g. if you already have an existing
database and want to work on it:
*/
 
Project.hasOne(User, { foreignKey: 'initiator_id' })
 
/*
Because Sequelize will use the model's name (first parameter of define) for
the accessor methods, it is also possible to pass a special option to hasOne:
*/
 
Project.hasOne(User, { as: 'Initiator' })
// Now you will get Project#getInitiator and Project#setInitiator
 
// Or let's define some self references
var Person = sequelize.define('Person', { /* ... */})
 
Person.hasOne(Person, {as: 'Father'})
// this will add the attribute FatherId to Person
 
// also possible:
Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'})
// this will add the attribute DadId to Person
 
// In both cases you will be able to do:
Person#setFather
Person#getFather
 
// If you need to join a table twice you can double join the same table
Team
.hasOne(Game, {foreignKey : 'homeTeamId'});
.hasOne(Game, {foreignKey : 'awayTeamId'});
Game
.belongsTo(Team);
 
 
// Since v1.3.0 you can also chain associations:
Project
.hasOne(User)
.hasOne(Deadline)
.hasOne(Attachment)
To get the association working the other way around &lpar;so from`User`to`Project`&rpar;&comma; it's necessary to do this&colon;
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
 
// One-way back associations
Project.belongsTo(User)
 
/*
In this example belongsTo will add an attribute UserId to the Project model!
That's the only difference to hasMany. Self references are working the very same way!
*/
### One-To-Many associations
One-To-Many associations are connecting one source with multiple targets&period; The targets however are again connected to exactly one specific source&period;
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
 
// OK. Now things get more complicated (not really visible to the user :)).
// First let's define a hasMany association
Project.hasMany(User, {as: 'Workers'})
This will add the attribute ProjectId or project\_id to User. Instances of Project will get the accessors getWorkers and setWorkers.
We could just leave it the way it is and let it be a one-way association.
But we want more! Let's define it the other way around by creating a many to many assocation in the next section:
### Many-To-Many associations
Many-To-Many associations are used to connect sources with multiple targets&period; Furthermore the targets can also have connections to multiple sources&period;
// again the Project association to User
Project.hasMany(User, { as: 'Workers' })
 
// now comes the association between User and Project
User.hasMany(Project)
 
/*
This will remove the attribute ProjectId (or project_id) from User and create
a new model called ProjectsUsers with the equivalent foreign keys ProjectId
(or project_id) and UserId (or user_id). If the attributes are camelcase or
not depends on the Model it represents.
 
Now you can use Project#getWorkers, Project#setWorkers, User#getTasks and
User#setTasks.
*/
 
// Of course you can also define self references with hasMany:
 
Person.hasMany(Person, { as: 'Children' })
// This will create the table ChildrenPersons which stores the ids of the objects.
 
// Since v1.5.0 you can also reference the same Model without creating a junction
// table (but only if each object will have just one 'parent'). If you need that,
// use the option foreignKey and set through to null
Person.hasMany(Person, { as: 'Children', foreignKey: 'ParentId', through: null })
 
// You can also use a predefined junction table using the option through:
Project.hasMany(User, {through: 'project_has_users'})
User.hasMany(Project, {through: 'project_has_users'})
If you want additional attributes in your join table&comma; you can define a model for the join table in sequelize&comma; before you define the association&comma; and then tell sequelize that it should use that model for joining&comma; instead of creating a new one&colon;
User = sequelize.define('User', {})
Project = sequelize.define('Project', {})
UserProjects = sequelize.define('UserProjects', {
status: DataTypes.STRING
})
 
User.hasMany(Project, { through: UserProjects })
Project.hasMany(User, { through: UserProjects })
The code above will add ProjectId and UserId to the UserProjects table&comma; and_remove any previsouly defined primary key attribute_&comma; - the table will be uniquely identified by the combination of the keys of the two tables&comma; and there is no reason to have other PK columns&period;
### Associating objects
Because Sequelize is doing a lot of magic&comma; you have to call`Sequelize&num;sync`after setting the associations&excl; Doing so will allow you the following&colon;
Project.hasMany(Task)
Task.hasMany(Project)
 
Project.create()...
Task.create()...
Task.create()...
 
// save them... and then:
project.setTasks([task1, task2]).success(function() {
// saved!
})
 
// ok now they are save... how do I get them later on?
project.getTasks().success(function(associatedTasks) {
// associatedTasks is an array of tasks
})
 
// You can also pass filters to the getter method.
// They are equal to the options you can pass to a usual finder method.
project.getTasks({ where: 'id > 10' }).success(function(tasks) {
// tasks with an id greater than 10 :)
})
 
// You can also only retrieve certain fields of a associated object.
// This example will retrieve the attibutes "title" and "id"
project.getTasks({attributes: ['title']}).success(function(tasks) {
// tasks with an id greater than 10 :)
})
To remove created associations you can just call the set method without a specific id&colon;
// remove the association with task1
project.setTasks([task2]).success(function(associatedTasks) {
// you will get task2 only
})
 
// remove 'em all
project.setTasks([]).success(function(associatedTasks) {
// you will get an empty array
})
 
// or remove 'em more directly
project.removeTask(task1).success(function() {
// it's gone
})
 
// and add 'em again
project.addTask(task1).success(function() {
// it's back again
})
You can of course also do it vice versa&colon;
// project is associated with task1 and task2
task2.setProject(null).success(function() {
// and it's gone
})
For hasOne&sol;belongsTo its basically the same&colon;
Task.hasOne(User, {as: "Author"})
Task#setAuthor(anAuthor)
Adding associations to a relation with a custom join table can be done in two ways &lpar;continuing with the associations defined in the previous chapter&rpar;&colon;
// Either by adding a property with the name of the join table model to the object, before creating the association
project.UserProjects = {
status: 'active'
}
u.addProject(project)
 
// Or by providing a second argument when adding the association, containing the data that should go in the join table
u.addProject(project, { status: 'active' })
 
 
// When associating multiple objects, you can combine the two options above. In this case the second argument
// will be treated as a defaults object, that will be used if no data is provided
project1.UserProjects = {
status: 'inactive'
}
 
u.setProjects([project1, project2], { status: 'active' })
// The code above will record inactive for project one, and active for project two in the join table
When getting data on an association that has a custom join table&comma; the data from the join table will be returned as a DAO instance&colon;
u.getProjects().success(function(projects) {
var project = projects[0]
 
if (project.UserProjects.status === 'active') {
// .. do magic
 
// since this is a real DAO instance, you can save it directly after you are done doing magic
project.UserProjects.save()
}
})
If you only need some of the attributes from the join table&comma; you can provide an array with the attributes you want&colon;
// This will select only name from the Projects table, and only status from the UserProjects table
user.getProjects({ attributes: ['name'], joinTableAttributes: ['status']})
### Check associations
Sequelize`v1&period;5&period;0`introduced methods which allows you&comma; to check if an object is already associated with another one &lpar;N&colon;M only&rpar;&period; Here is how you'd do it&colon;
// check if an object is one of associated ones:
Project.create({ /* */ }).success(function(project) {
User.create({ /* */ }).success(function(user) {
project.hasUser(user).success(function(result) {
// result would be false
project.addUser(user).success(function() {
project.hasUser(user).success(function(result) {
// result would be true
})
})
})
})
})
 
// check if all associated objects are as expected:
// let's assume we have already a project and two users
project.setUsers([user1, user2]).success(function() {
project.hasUsers([user1]).success(function(result) {
// result would be false
project.hasUsers([user1, user2]).success(function(result) {
// result would be true
})
})
})
### Foreign Keys
When you create associations between your models in sequelize, foreign key references with constraints will automatically be created. The setup below:
var Task = this.sequelize.define('Task', { title: Sequelize.STRING })
, User = this.sequelize.define('User', { username: Sequelize.STRING })
 
User.hasMany(Task)
Task.belongsTo(User)
Will generate the following SQL:
CREATE TABLE IF NOT EXISTS `User` (
`id` INTEGER PRIMARY KEY,
`username` VARCHAR(255)
);
CREATE TABLE IF NOT EXISTS `Task` (
`id` INTEGER PRIMARY KEY,
`title` VARCHAR(255),
`user_id` INTEGER
);
To add references constraints to the columns, you can pass the options `onUpdate`and`onDelete`to the association calls. The validation options are`RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL`, for example:
User.hasMany(Task, { onDelete: 'SET NULL', onUpdate: 'CASCADE' })
CREATE TABLE IF NOT EXISTS `Task` (
`id` INTEGER PRIMARY KEY,
`title` VARCHAR(255),
`user_id` INTEGER REFERENCES `User` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
);
#### Enforcing a foreign key reference without constraints
Some times you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition
, and mark the relations between them.
var Series, Trainer, Video
 
// Series has a trainer_id=Trainer.id foreign reference key after we call Trainer.hasMany(series)
Series = sequelize.define('Series', {
title: DataTypes.STRING,
sub_title: DataTypes.STRING,
description: DataTypes.TEXT,
 
// Set FK relationship (hasMany) with `Trainer`
trainer_id: {
type: DataTypes.INTEGER,
references: "Trainer",
referencesKey: "id"
}
})
 
Trainer = sequelize.define('Trainer', {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING
});
 
// Video has a series_id=Series.id foreign reference key after we call Series.hasOne(Video)...
Video = sequelize.define('Video', {
title: DataTypes.STRING,
sequence: DataTypes.INTEGER,
description: DataTypes.TEXT,
 
// set relationship (hasOne) with `Series`
series_id: {
type: DataTypes.INTEGER,
references: Series, // Can be both a string representing the table name, or a reference to the model
referencesKey: "id"
}
});
 
Series.hasOne(Video);
Trainer.hasMany(Series);
## Hooks
Hooks (also known as callbacks or lifecycle events), are functions which are called before and after calls in sequelize are executed. For example, if you want to always set a value on a model before saving it, you can add a`beforeUpdate`hook.
### Order of Operations
(1)
beforeBulkCreate(daos, fields, fn)
beforeBulkDestroy(daos, fields, fn)
beforeBulkUpdate(daos, fields, fn)
(2)
beforeValidate(dao, fn)
(-)
validate
(3)
afterValidate(dao, fn)
(4)
beforeCreate(dao, fn)
beforeDestroy(dao, fn)
beforeUpdate(dao, fn)
(-)
create
destroy
update
(5)
afterCreate(dao, fn)
afterDestroy(dao, fn)
afterUpdate(dao, fn)
(6)
afterBulkCreate(daos, fields, fn)
afterBulkDestory(daos, fields, fn)
afterBulkUpdate(daos, fields, fn)
### Declaring Hooks
There are currently three ways to programmatically add hooks. A hook function always runs asynchronousĺy, and can be resolved either by calling a callback (passed as the last argument),
or by returning a promise.
// Method 1 via the .define() method
var User = sequelize.define('User', {
username: DataTypes.STRING,
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
}, {
hooks: {
beforeValidate: function(user, fn) {
user.mood = 'happy'
fn(null, user)
},
afterValidate: function(user, fn) {
user.username = 'Toni'
fn(null, user)
}
}
})
// Method 2 via the .hook() method
var User = sequelize.define('User', {
username: DataTypes.STRING,
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
})
User.hook('beforeValidate', function(user, fn) {
user.mood = 'happy'
fn(null, user)
})
User.hook('afterValidate', function(user) {
return sequelize.Promise.reject("I'm afraid I can't let you do that!")
})
// Method 3 via the direct method
var User = sequelize.define('User', {
username: DataTypes.STRING,
mood: {
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
}
})
User.beforeValidate(function(user) {
user.mood = 'happy'
return sequelize.Promise.resolve(user)
})
User.afterValidate(function(user, fn) {
user.username = 'Toni'
fn(null, user)
})
#### Instance hooks
The following hooks will emit whenever you're editing a single object...
beforeValidate
afterValidate
beforeCreate / beforeUpdate / beforeDestroy
afterCreate / afterUpdate / afterDestroy
// ...define ...
User.beforeCreate(function(user, fn) {
if (user.accessLevel > 10 && user.username !== "Boss") {
return fn("You can't grant this user an access level above 10!")
}
return fn()
})
This example will emit an error:
User.create({username: 'Not a Boss', accessLevel: 20}).error(function(err) {
console.log(err) // You can't grant this user an access level above 10!
})
The following example would emit a success event:
User.create({username: 'Boss', accessLevel: 20}).success(function(user) {
console.log(user) // user object with username as Boss and accessLevel of 20
})
#### Model hooks
Sometimes you'll be editing more than one record at a time by utilizing the`bulkCreate, update, destroy`methods on the model. The following will emit whenever you're using one of those methods.
beforeBulkCreate / beforeBulkUpdate / beforeBulkDestroy
afterBulkCreate / afterBulkUpdate / afterBulkDestroy
If you want to emit hooks for each individual record, along with the bulk hooks you can pass`individualHooks: true`to the call.
Model.destroy({accessLevel: 0}, {individualHooks: true})
// Will select all records that are about to be deleted and emit before- + after- Destroy on each instance
Model.update({username: 'Toni'}, {accessLevel: 0}, {individualHooks: true})
// Will select all records that are about to be updated and emit before- + after- Update on each instance
Model.bulkCreate({accessLevel: 0}, null, {individualHooks: true})
// Will select all records that are about to be deleted and emit before- + after- Create on each instance
Some model hooks have two or three parameters sent to each hook depending on it's type.
Model.beforeBulkCreate(function(records, fields, fn) {
// records = the first argument sent to .bulkCreate
// fields = the second argument sent to .bulkCreate
})
Model.bulkCreate([
{username: 'Toni'}, // part of records argument
{username: 'Tobi'} // part of records argument
], ['username'] /* part of fields argument */)
Model.beforeBulkUpdate(function(attributes, where, fn) {
// attributes = first argument sent to Model.update
// where = second argument sent to Model.update
})
Model.update({gender: 'Male'} /*attributes argument*/, {username: 'Tom'} /*where argument*/)
Model.beforeBulkDestroy(function(whereClause, fn) {
// whereClause = first argument sent to Model.destroy
})
Model.destroy({username: 'Tom'} /*whereClause argument*/)
## Associations
For the most part hooks will work the same for instances when being associated except a few things
1. When using add/set\[s\] functions the beforeUpdate/afterUpdate hooks will run.
2. The only way to call beforeDestroy/afterDestroy hooks are on associations with`onDelete: 'cascade'`and the option`hooks: true`. For instance:
var Projects = sequelize.define('Projects', {
title: DataTypes.STRING
})
var Tasks = sequelize.define('Tasks', {
title: DataTypes.STRING
})
Projects.hasMany(Tasks, {onDelete: 'cascade', hooks: true})
Tasks.belongsTo(Projects)
This code will run beforeDestroy/afterDestroy on the Tasks table. Sequelize, by default, will try to optimize your queries as much as possible.
When calling cascade on delete, Sequelize will simply execute a
DELETE FROM `table` WHERE associatedIdentifiier = associatedIdentifier.primaryKey
However, adding`hooks: true`explicitly tells Sequelize that optimization is not of your concern and will perform a`SELECT`on the associated objects and destroy each instance one by one in order to be able to call the hooks with the right parameters.
## Installation
You have two options to install Sequelize&colon;
1&period; Install it via NPM&colon;
# Use npm on the commandline:
npm install sequelize
// Then require the installed library in your application code:
var Sequelize = require("sequelize")
2&period; Download the code from the git repository and require it's entry file index&period;js&colon;
# Checkout the current code from the repository using the commandline
cd path/to/lib
git clone git://github.com/sequelize/sequelize.git
Then require the installed library in your application code&colon;
var Sequelize = require(__dirname + "/lib/sequelize/index")
This will make the class`Sequelize`available&period;
## Instances
### Building a not-persistant instance
In order to create instances of defined classes just do as follows&period; You might recognize the syntax if you coded Ruby in the past&period; Using the`build`-method will return an unsaved object&comma; which you explicitly have to save&period;
var project = Project.build({
title: 'my awesome project',
description: 'woot woot. this will make me a rich man'
})
 
var task = Task.build({
title: 'specify the project idea',
description: 'bla',
deadline: new Date()
})
Built instances will automatically get default values when they were defined&colon;
// first define the model
var Task = sequelize.define('Project', {
title: Sequelize.STRING,
rating: { type: Sequelize.STRING, defaultValue: 3 }
})
 
// now instantiate an object
var task = Task.build({title: 'very important task'})
 
task.title // ==> 'very important task'
task.rating // ==> 3
To get it stored in the database&comma; use the`save`-method and catch the events ... if needed&colon;
project.save().success(function() {
// my nice callback stuff
})
 
task.save().error(function(error) {
// mhhh, wth!
})
 
// you can also build, save and access the object with chaining:
Task
.build({ title: 'foo', description: 'bar', deadline: new Date() })
.save()
.success(function(anotherTask) {
// you can now access the currently saved task with the variable anotherTask... nice!
}).error(function(error) {
// Ooops, do some error-handling
})
### Creating persistant instances
Besides constructing objects&comma; that needs an explicit save call to get stored in the database&comma; there is also the possibility to do all those steps with one single command&period; It's called`create`&period;
Task.create({ title: 'foo', description: 'bar', deadline: new Date() }).success(function(task) {
// you can now access the newly created task via the variable task
})
Sequelize`v1&period;5&period;0`introduced the possibility to define attributes which can be set via the create method&period; This can be especially very handy if you create database entries based on a form which can be filled by a user&period; Using that would for example allow you to restrict the`User`model to set only a username and an address but not an admin flag&colon;
User.create({ username: 'barfooz', isAdmin: true }, [ 'username' ]).success(function(user) {
// let's assume the default of isAdmin is false:
console.log(user.values) // => { username: 'barfooz', isAdmin: false }
})
### Updating / Saving / Persisting an instance
Now lets change some values and save changes to the database&period;&period;&period; There are two ways to do that&colon;
// way 1
task.title = 'a very different title now'
task.save().success(function() {})
 
// way 2
task.updateAttributes({
title: 'a very different title now'
}).success(function() {})
Since`v1&period;4&period;1`it's also possible to define which attributes should be saved when calling`save`&comma; by passing an array of column names&period; This is useful when you set attributes based on a previously defined object&period; E&period;g&period; if you get the values of an object via a form of a web app&period; Furthermore this is used internally for`updateAttributes`&period; This is how it looks like&colon;
task.title = 'foooo'
task.description = 'baaaaaar'
task.save(['title']).success(function() {
// title will now be 'foooo' but description is the very same as before
})
 
// The equivalent call using updateAttributes looks like this:
task.updateAttributes({ title: 'foooo', description: 'baaaaaar'}, ['title']).success(function() {
// title will now be 'foooo' but description is the very same as before
})
### Destroying / Deleting persistant instances
Once you created an object and got a reference to it&comma; you can delete it from the database&period; The relevant method is`destroy`&colon;
Task.create({ title: 'a task' }).success(function(task) {
// now you see me...
 
task.destroy().success(function() {
// now i'm gone :)
})
})
### Working in bulk (updating multiple rows at once)
In addition to updating a single instance, you can also create, update, and delete multiple instances at once. The functions you are looking for are called
* `Model.bulkCreate`
* `Model.update`
* `Model.destroy`
Since you are working with multiple models, the callbacks will not return DAO instances. BulkCreate will return an array of model instances/DAOs, they will however, unlike `create`, not have the resulting values of autoIncrement attributes. `update `and `destroy`will return the number of affected rows.
First lets look at bulkCreate
User.bulkCreate([
{ username: 'barfooz', isAdmin: true },
{ username: 'foo', isAdmin: true },
{ username: 'bar', isAdmin: false }
]).success(function() { // Notice: There are no arguments here, as of right now you'll have to...
User.findAll().success(function(users) {
console.log(users) // ... in order to get the array of user objects
})
})
To update several rows at once:
Task.bulkCreate([
{subject: 'programming', status: 'executing'},
{subject: 'reading', status: 'executing'},
{subject: 'programming', status: 'finished'}
]).success(function() {
Task.update(
{status: 'inactive'} /* set attributes' value */,
{subject: 'programming'} /* where criteria */
).success(function(affectedRows) {
// affectedRows will be 2
Task.findAll().success(function(tasks) {
console.log(tasks) // the 'programming' tasks will both have a status of 'inactive'
})
})
})
And delete them:
Task.bulkCreate([
{subject: 'programming', status: 'executing'},
{subject: 'reading', status: 'executing'},
{subject: 'programming', status: 'finished'}
]).success(function() {
Task.destroy(
{subject: 'programming'} /* where criteria */,
{truncate: true /* truncate the whole table, ignoring where criteria */} /* options */
).success(function(affectedRows) {
// affectedRows will be 2
Task.findAll().success(function(tasks) {
console.log(tasks) // no programming, just reading :(
})
})
})
If you are accepting values directly from the user, it might be beneficial to limit the columns that you want to actually insert.`bulkCreate&lpar;&rpar;`accepts a second parameter &lpar;an array&rpar; to let it know which fields you want to build explicitly
User.bulkCreate([
{ username: 'foo' },
{ username: 'bar', admin: true}
], ['username']).success(function() {
// nope bar, you can't be admin!
})
 
// an easier way to keep track of which fields you want to explicitly build, use Object.keys() like so
var objects = [
{ username: 'foo' },
{ username: 'bar' }
]
 
User.bulkCreate(objects, Object.keys(objects)).success(function() {
// ...
})
`bulkCreate&lpar;&rpar;`was originally made to be a mainstream&sol;fast way of inserting records&comma; however&comma; sometimes you want the luxury of being able to insert multiple rows at once without sacrificing model validations even when you explicitly tell Sequelize which columns to sift through&period; You can do by adding a third parameter of an object with the value of`&lcub;validate&colon; true&rcub;`
var Tasks = sequelize.define('Task', {
name: {
type: Sequelize.STRING,
validate: {
notNull: { args: true, msg: 'name cannot be null' }
}
},
code: {
type: Sequelize.STRING,
validate: {
len: [3, 10]
}
}
})
 
Tasks.bulkCreate([
{name: 'foo', code: '123'},
{code: '1234'},
{name: 'bar', code: '1'}
], null, {validate: true}).error(function(errors) {
/* console.log(errors) would look like:
[
{
"record": {
"code": "1234"
},
"errors": {
"name": [
"name cannot be null"
]
}
},
{
"record": {
"name": "bar",
"code": "1"
},
"errors": {
"code": [
"String is not in range: code"
]
}
}
]
*/
})
### Values of an instance
If you log an instance you will notice&comma; that there is a lot of additional stuff&period; In order to hide such stuff and reduce it to the very interesting information&comma; you can use the`values`-attribute&period; Calling it will return only the values of an instance&period;
Person.create({
name: 'Rambow',
firstname: 'John'
}).success(function(john) {
console.log(john.values)
})
 
// result:
 
// { name: 'Rambow',
// firstname: 'John',
// id: 1,
// createdAt: Tue, 01 May 2012 19:12:16 GMT,
// updatedAt: Tue, 01 May 2012 19:12:16 GMT
// }
**Hint&colon;**You can also transform an instance into JSON by using`JSON&period;stringify&lpar;instance&rpar;`&period; This will basically return the very same as`values`&period;
### Reloading instances
If you need to get your instance in sync&comma; you can use the method`reload`&period; It will fetch the current data from the database and overwrite the attributes of the model on which the method has been called on&period;
Person.find({ where: { name: 'john' } }).success(function(person) {
person.name = 'jane'
console.log(person.name) // 'jane'
 
person.reload().success(function() {
console.log(person.name) // 'john'
})
})
### Incrementing certain values of an instance
In order to increment values of an instance without running into concurrency issues&comma; you may use`increment`&period;
First of all you can define a field and the value you want to add to it&period;
User.find(1).success(function(user) {
user.increment('my-integer-field', 2).success(/* ... */)
})
Second&comma; you can define multiple fields and the value you want to add to them&period;
User.find(1).success(function(user) {
user.increment([ 'my-integer-field', 'my-very-other-field' ], 2).success(/* ... */)
})
Third&comma; you can define an object containing fields and its increment values&period;
User.find(1).success(function(user) {
user.increment({
'my-integer-field': 2,
'my-very-other-field': 3
}).success(/* ... */)
})
### Decrementing certain values of an instance
In order to decrement values of an instance without running into concurrency issues&comma; you may use`decrement`&period;
First of all you can define a field and the value you want to add to it&period;
User.find(1).success(function(user) {
user.decrement('my-integer-field', 2).success(/* ... */)
})
Second&comma; you can define multiple fields and the value you want to add to them&period;
User.find(1).success(function(user) {
user.decrement([ 'my-integer-field', 'my-very-other-field' ], 2).success(/* ... */)
})
Third&comma; you can define an object containing fields and its decrement values&period;
User.find(1).success(function(user) {
user.decrement({
'my-integer-field': 2,
'my-very-other-field': 3
}).success(/* ... */)
})
## Migrations
Sequelize`v1&period;3&period;0`introduced migrations&period; With those mechanism you can transform your existing database into another state and vice versa&period; Those state transitions are saved in migration files&comma; which describe the way how to get to the new state and how to revert the changes in order to get back to the old state&period;
### The binary
In order to run migrations&comma; sequelize comes with a handy binary file which can setup your project and run migrations&period; The following snippet shows the possible things&colon;
sequelize -h
sequelize --help
# prints the help
sequelize -V
sequelize --version
# prints the version
sequelize -i
sequelize --init
# creates a migration folder
# creates a config folder
# saves a config.json inside the config folder
sequelize -e [environment]
sequelize --env [environment]
# Use the passed environment. Default: development
sequelize -i -f
sequelize --init --force
# forced creation of migration and config folder
# existing data will be deleted first
sequelize -m
sequelize --migrate
# needs a valid config.json
# runs pending migrations
# saves successfully executed migrations inside the database
sequelize -m -u
sequelize --migrate --undo
# needs a valid config.json
# reverts the last successfull migration
# when there were multiple executed migrations, all of them are reverted
sequelize -c [migration-name]
sequelize --create-migration [migration-name]
# creates the migrations folder
# creates a file with current timestamp + migration-name
# migration-name has the default 'unnamed-migration'
sequelize -p [path]
sequelize --migration-path [path]
# Defines the path to the migration directory.
sequelize -o [path]
sequelize --options-path [path]
# Defines the path to the options file.
# The options file (.js or .json) needs to return an object.
# Keys / values references cli options
# e.g.: { migrationPath: 'db/migrations' }
sequelize --config [path]
# Defines the path to the configuration file.
sequelize --coffee
# Enables coffeescript support.
### Skeleton
The following skeleton shows a typical migration file&period; All migrations are expected to be located in a folder called`migrations`at the very top of the project&period; Sequelize`1&period;4&period;1`added the possibility to let the sequelize binary generate a migration skeleton&period; See the aboves section for more details&period;
module.exports = {
up: function(migration, DataTypes, done) {
// logic for transforming into the new state
done() // sets the migration as finished
},
 
down: function(migration, DataTypes, done) {
// logic for reverting the changes
done() // sets the migration as finished
}
}
The passed`migration`object can be used to modify the database&period; The`DataTypes`object stores the available data types such as`STRING`or`INTEGER`&period; The third parameter is a callback function which needs to be called once everything was executed&period; The first parameter of the callback function can be used to pass a possible error&period; In that case&comma; the migration will be marked as failed&period; Here is some code&colon;
module.exports = {
up: function(migration, DataTypes, done) {
migration.dropAllTables().complete(done)
 
// equals:
migration.dropAllTables().complete(function(err) {
if (err) {
done(err)
} else {
done(null)
}
})
}
}
The available methods of the migration object are the following&period;
### Functions
Using the`migration`object describe before&comma; you will have access to most of already introduced functions&period; Furthermore there are some other methods&comma; which are designed to actually change the database schema&period;
#### createTable&lpar;tableName&comma; attributes&comma; options&rpar;
This method allows creation of new tables&period; It is allowed to pass simple or complex attribute definitions&period; You can define the encoding of the table and the table's engine via options
migration.createTable(
'nameOfTheNewTable',
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: DataTypes.DATE
},
updatedAt: {
type: DataTypes.DATE
},
attr1: DataTypes.STRING,
attr2: DataTypes.INTEGER,
attr3: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false
}
},
{
engine: 'MYISAM', // default: 'InnoDB'
charset: 'latin1' // default: null
}
)
#### dropTable&lpar;tableName&rpar;
This method allows deletion of an existing table&period;
migration.dropTable('nameOfTheExistingTable')
#### dropAllTables&lpar;&rpar;
This method allows deletion of all existing tables in the database&period;
migration.dropAllTables()
#### renameTable&lpar;before&comma; after&rpar;
This method allows renaming of an existing table&period;
migration.renameTable('Person', 'User')
#### showAllTables&lpar;&rpar;
This method returns the name of all existing tables in the database&period;
migration.showAllTables().success(function(tableNames) {})
#### describeTable&lpar;tableName&rpar;
This method returns an array of hashes containing information about all attributes in the table&period;
migration.describeTable('Person').success(function(attributes) {
/*
attributes will be something like:
 
{
name: {
type: 'VARCHAR(255)', // this will be 'CHARACTER VARYING' for pg!
allowNull: true,
defaultValue: null
},
isBetaMember: {
type: 'TINYINT(1)', // this will be 'BOOLEAN' for pg!
allowNull: false,
defaultValue: false
}
}
*/
})
#### addColumn&lpar;tableName&comma; attributeName&comma; dataTypeOrOptions&rpar;
This method allows adding columns to an existing table&period; The data type can be simple or complex&period;
migration.addColumn(
'nameOfAnExistingTable',
'nameOfTheNewAttribute',
DataTypes.STRING
)
 
// or
 
migration.addColumn(
'nameOfAnExistingTable',
'nameOfTheNewAttribute',
{
type: DataTypes.STRING,
allowNull: false
}
)
#### removeColumn&lpar;tableName&comma; attributeName&rpar;
This method allows deletion of a specific column of an existing table&period;
migration.removeColumn('Person', 'signature')
#### changeColumn&lpar;tableName&comma; attributeName&comma; dataTypeOrOptions&rpar;
This method changes the meta data of an attribute&period; It is possible to change the default value&comma; allowance of null or the data type&period; Please make sure&comma; that you are completely describing the new data type&period; Missing information are expected to be defaults&period;
migration.changeColumn(
'nameOfAnExistingTable',
'nameOfAnExistingAttribute',
DataTypes.STRING
)
 
// or
 
migration.changeColumn(
'nameOfAnExistingTable',
'nameOfAnExistingAttribute',
{
type: DataTypes.FLOAT,
allowNull: false,
default: 0.0
}
)
#### renameColumn&lpar;tableName&comma; attrNameBefore&comma; attrNameAfter&rpar;
This methods allows renaming attributes&period;
migration.renameColumn('Person', 'signature', 'sig')
#### addIndex&lpar;tableName&comma; attributes&comma; options&rpar;
This methods creates indexes for specific attributes of a table&period; The index name will be automatically generated if it is not passed via in the options &lpar;see below&rpar;&period;
// This example will create the index person_firstname_lastname
migration.addIndex('Person', ['firstname', 'lastname'])
// This example will create a unique index with the name SuperDuperIndex using the optional 'options' field.
// Possible options:
// - indicesType: UNIQUE|FULLTEXT|SPATIAL
// - indexName: The name of the index. Default is __
// - parser: For FULLTEXT columns set your parser
// - indexType: Set a type for the index, e.g. BTREE. See the documentation of the used dialect
migration.addIndex(
'Person',
['firstname', 'lastname'],
{
indexName: 'SuperDuperIndex',
indicesType: 'UNIQUE'
}
)
#### removeIndex&lpar;tableName&comma; indexNameOrAttributes&rpar;
This method deletes an existing index of a table&period;
migration.removeIndex('Person', 'SuperDuperIndex')
 
// or
 
migration.removeIndex('Person', ['firstname', 'lastname'])
### Programmatic use
If you need to interact with the migrator within your code,
you can easily achieve that via `sequelize.getMigrator`.
You can specify the path to your migrations as well as a pattern
which represents the files that contain the migrations.
var migrator = sequelize.getMigrator({
path: process.cwd() + '/database/migrations',
filesFilter: /\.coffee$/
})
Once you have a migrator object, you can run its migration
with `migrator.migrate`. By default, this will
execute all the up methods within your pending migrations.
If you want to rollback a migration, just call it like this:
migrator
.migrate({ method: 'down' })
.success(function() {
// The migrations have been executed!
})
## Misc
### Compatibility
Sequelize is compatible to the following versions of Node.JS:
* 0.8.x
* 0.10.x
### Asynchronicity
Since`v1&period;3&period;0`there are multiple ways of adding listeners to asynchronous requests&period; First of all&comma; each time you call a finder method or save an object&comma; sequelize triggers asynchronous logic&period; To react to the success or the failure &lpar;or both&rpar; of the request&comma; you can do the following&colon;
// the old, pre-v1.3.0 way
Model.findAll().on('success', function(models) { /* foo */ })
Model.findAll().on('failure', function(err) { /* bar */ })
 
// the new, >=v1.3.0 way
// each one is valid
Model.findAll().on('success', function(models) { /* foo */ })
Model.findAll().success(function(models) { /* foo */ })
Model.findAll().ok(function(models) { /* foo */ })
 
// Model.findAll().on('failure', function(err) { /* bar */ }) ==> invalid since v1.5.0
Model.findAll().on('error', function(err) { /* bar */ }) // ==> new since v1.5.0
Model.findAll().error(function(err) { /* bar */ })
Model.findAll().failure(function(err) { /* bar */ })
Model.findAll().fail(function(err) { /* bar */ })
 
Model.findAll().complete(function(err, result) { /* bar */ })
Model.findAll().done(function(err, result) { /* bar */ })
 
// As of 1.7.0 we support Promises/A
var self = User
 
user.find(1).then(function(user1) {
return user1.increment(['aNumber'], 2)
}).then(function(user2) {
return user.find(1)
}).then(function(user3) {
console.log(user3.aNumber) // 2
}, function(err) {
// err...
})
 
 
// For functions with multiple success values (e.g. findOrCreate) there is also spread
 
user.findOrCreate(...).spread(function(user, wasCreated) {
// all arguments are passed
})
user.findOrCreate(...).then(function(user) {
// only the first argument is passed
})
**Please notice&colon;**Since v1&period;5&period;0 the 'error' event is used to notify about errors&period; If such events aren't caught however&comma; Node&period;JS will throw an error&period; So you would probably like to catch them &colon;D
### Additional links
If you want to keep track about latest development of sequelize or to just discuss things with other sequelize users you might want to take a look at the following resources&colon;
* [Twitter&colon; &commat;sdepold][0]
* [Twitter&colon; &commat;sequelizejs][1]
* [ADN&colon; &commat;sdepold][2]
* [IRC&colon; sequelizejs&commat;freenode&period;net][3]
* [XING][4]
* [Facebook][5]
### Company & Projects
Here is a list of companies and projects that are using Sequelize in real world applications&colon;
#### [Shutterstock][6]
Shutterstock Images LLC is a leading global provider of high-quality stock footage&comma; stock photography&comma; vectors and illustrations to creative industry professionals around the world&period; Shutterstock works closely with its growing contributor community of artists&comma; photographers&comma; videographers and illustrators to curate a global marketplace for royalty-free&comma; top-quality imagery&period; Shutterstock adds tens of thousands of rights-cleared images and footage clips each week&comma; with more than 18 million files currently available&period;
#### [Clevertech][7]
Clevertech builds web and mobile applications for startups using Lean and Agile methodologies. Clevertech relies on Sequelize for its applications, its speed, versatility and data flexibility. Clevertech contributes back to open source development and its expert developers support the continuing effort to make sequelize the best ORM for Node projects.
#### [Metamarkets][8]
Metamarkets enables buyers and sellers of digital media to visualize insights and make decisions with real-time pricing&comma; performance&comma; and audience data&period;
#### [Innofluence][9]
On Innofluence&comma; people meet and engage in challenges&comma; questions&comma; and dilemmas -- big and small -- to be inspired&comma; to explore&comma; and to find better solutions and answers&period; Together&period; Ask the network a question&comma; and they will in return reply with Input&comma; exciting points of view&comma; and new reflections&period; Or help and inspire others in need of your input&period;
#### [Using sequelize&quest;][10]
If you want to get listed here&comma; just drop me a line or send me a pull-request on Github&excl;
[0]: http://twitter.com/sdepold
[1]: http://twitter.com/sequelizejs
[2]: https://alpha.app.net/sdepold
[3]: irc://irc.freenode.net/sequelizejs
[4]: https://www.xing.com/net/priec1b5cx/sequelize
[5]: https://www.facebook.com/sequelize
[6]: http://www.shutterstock.com
[7]: http://www.clevertech.biz
[8]: http://metamarkets.com/
[9]: https://innofluence.com
[10]: https://github.com/sequelize/sequelize/tree/gh-pages
## Models
### Definition
To define mappings between a model and a table&comma; use the`define`method&period; Sequelize will then automatically add the attributes`createdAt`and`updatedAt`to it&period; So you will be able to know when the database entry went into the db and when it was updated the last time&period;
If you do not want timestamps on your models, only want some timestamps, or you are working with an existing database where the columns are named something else, jump straight onto [configuration ][0]to see how to do that.
var Project = sequelize.define('Project', {
title: Sequelize.STRING,
description: Sequelize.TEXT
})
 
var Task = sequelize.define('Task', {
title: Sequelize.STRING,
description: Sequelize.TEXT,
deadline: Sequelize.DATE
})
You can also set some options on each column&colon;
var Foo = sequelize.define('Foo', {
// instantiating will automatically set the flag to true if not set
flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},
 
// default values for dates => current time
myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },
 
// setting allowNull to false will add NOT NULL to the column, which means an error will be
// thrown from the DB when the query is executed if the column is null. If you want to check that a value
// is not null before querying the DB, look at the validations section below.
title: { type: Sequelize.STRING, allowNull: false},
 
// Creating two objects with the same value will throw an error. The unique property can be either a
// boolean, or a string. If you provide the same string for multiple columns, they will form a
// composite unique key.
someUnique: {type: Sequelize.STRING, unique: true},
uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex'},
uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}
 
// Go on reading for further information about primary keys
identifier: { type: Sequelize.STRING, primaryKey: true},
 
// autoIncrement can be used to create auto_incrementing integer columns
incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }
 
// Comments can be specified for each field for MySQL and PG
hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" }
})
The comment option can also be used on a table&comma; see [model configuration][0]
### Data types
Sequelize currently supports the following datatypes&colon;
Sequelize.STRING // VARCHAR(255)
Sequelize.STRING(1234) // VARCHAR(1234)
Sequelize.STRING.BINARY // VARCHAR BINARY
Sequelize.TEXT // TEXT
 
Sequelize.INTEGER // INTEGER
Sequelize.BIGINT // BIGINT
Sequelize.BIGINT(11) // BIGINT(11)
Sequelize.FLOAT // FLOAT
Sequelize.FLOAT(11) // FLOAT(11)
Sequelize.FLOAT(11, 12) // FLOAT(11,12)
 
Sequelize.DECIMAL // DECIMAL
Sequelize.DECIMAL(10, 2) // DECIMAL(10,2)
 
Sequelize.DATE // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
Sequelize.BOOLEAN // TINYINT(1)
 
Sequelize.ENUM('value 1', 'value 2') // An ENUM with allowed values 'value 1' and 'value 2'
Sequelize.ARRAY(Sequelize.TEXT) // Defines an array. PostgreSQL only.
 
Sequelize.BLOB // BLOB (bytea for PostgreSQL)
Sequelize.BLOB('tiny') // TINYBLOB (bytea for PostgreSQL. Other options are medium and long)
Sequelize.UUID // UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically)
The BLOB data type allows you to insert data both as strings and as buffers&period; When you do a find or findAll on a model which has a BLOB column&comma; that data will always be returned as a buffer&period;
In addition to the type mentioned above&comma; integer&comma; bigint and float also support unsigned and zerofill properties&comma; which can be combined in any order&colon;
Sequelize.INTEGER.UNSIGNED // INTEGER UNSIGNED
Sequelize.INTEGER(11).UNSIGNED // INTEGER(11) UNSIGNED
Sequelize.INTEGER(11).ZEROFILL // INTEGER(11) ZEROFILL
Sequelize.INTEGER(11).ZEROFILL.UNSIGNED // INTEGER(11) UNSIGNED ZEROFILL
Sequelize.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
_The examples above only show integer&comma; but the same can be done with bigint and float_
Usage in object notation&colon;
// for enums:
sequelize.define('model', {
states: {
type: Sequelize.ENUM,
values: ['active', 'pending', 'deleted']
}
})
### Getters & setters
It is possible to define 'object-property' getters and setter functions on your models&comma; these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties&period;
Getters and Setters can be defined in 2 ways &lpar;you can mix and match these 2 approaches&excl;&rpar;&colon;
* as part of a single property definition
* as part of a model options
**N&period;B&period;&colon;**If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence&period;
#### Defining as part of a property
var Foo = sequelize.define('Foo', {
name: { Sequelize.STRING },
title: {
type : Sequelize.STRING,
allowNull: false,
get : function() {
/*
do your magic here and return something!
'this' allows you to access attributes of the model.
 
example: this.getDataValue('name') works
*/
},
set : function(v) { /* do your magic with the input here! */ }
}
});
#### Defining as part of the model options
Below is an example of defining the getters and setters in the model options&comma; notice the`title&UnderBar;slug`getter&comma; it shows how you can define`pseudo`properties on your models&excl; &lpar;the`slugify&lpar;&rpar;`function was taken from the [Underscore&period;String module][1]&comma; it is slightly modified here so that the example remains self-contained&rpar;&comma; note that the`this&period;title`reference in the`title&UnderBar;slug`getter function will trigger a call to the`title`getter function&period; if you do not want that then
use the`getDataValue&lpar;&rpar;`method &lpar;[see below][2]&rpar;&period;
var defaultToWhiteSpace = function(characters) {
if (characters == null)
return '\\s';
else if (characters.source)
return characters.source;
else
return ;
};
 
var slugify function(str) {
var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøśùúüûñçżź",
to = "aaaaaaaaceeeeeiiiilnoooooosuuuunczz",
regex = new RegExp('[' + from.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + ']', 'g');
 
if (str == null) return '';
 
str = String(str).toLowerCase().replace(regex, function(c) {
return to.charAt(from.indexOf(c)) || '-';
});
 
return str.replace(/[^\w\s-]/g, '').replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}
 
var Foo = sequelize.define('Foo', {
title: {
type : Sequelize.STRING,
allowNull: false,
}
}, {
 
getterMethods : {
title : function() { /* do your magic here and return something! */ },
title_slug : function() { return slugify(this.title); }
},
 
setterMethods : {
title : function(v) { /* do your magic with the input here! */ },
}
});
#### Helper functions for use inside getter&sol;setter definitions
* retrieving an underlying property value&quest; always use`this&period;getDataValue&lpar;&rpar;`&comma; e&period;g&period;&colon;
/* a getter for 'title' property */
function() {
return this.getDataValue('title');
}
* setting an underlying property value&quest; always use`this&period;setDataValue&lpar;&rpar;`&comma; e&period;g&period;&colon;
/* a setter for 'title' property */
function(title) {
return this.setDataValue('title', title.toString().toLowerCase());
}
**N.B.: **It is important to stick to using the`setDataValue&lpar;&rpar;`and`getDataValue&lpar;&rpar;`functions &lpar;as opposed to accessing the underlying "data values" property directly&rpar; - doing so protects your custom getters and setters from changes in the underlying model implementations &lpar;i&period;e&period; how and where data values are stored in your model instances&rpar;
#### Setter methods and Object Initialization
&excl;&excl;&excl;TODO&colon; write about how setters affect object initialization &lpar;both creating new objects with Model&period;build and retrieving existing objects from storage&rpar; &excl;&excl;&excl;&excl;&excl;
### Validations
In`v1&period;3&period;0`model validations have been added&period; They allow you to specify format&sol;content&sol;inheritance validations for each attribute of the model&period; You can perform the validation by calling the`validate&lpar;&rpar;`method on an instance before saving&period; The validations are implemented by [validator][3]&comma; and we are currently using v&period; 3&period;2&period;x&period;
**Note&colon; **In`v1&period;7&period;0`validations will now be called when executing the`build&lpar;&rpar;`or`create&lpar;&rpar;`functions&period;
var ValidateMe = sequelize.define('Foo', {
foo: {
type: Sequelize.STRING,
validate: {
is: ["^[a-z]+$",'i'], // will only allow letters
not: ["[a-z]",'i'], // will not allow letters
isEmail: true, // checks for email format (foo@bar.com)
isUrl: true, // checks for url format (http://foo.com)
isIP: true, // checks for IPv4 (129.89.23.1) or IPv6 format
isIPv4: true, // checks for IPv4 (129.89.23.1)
isIPv6: true, // checks for IPv6 format
isAlpha: true, // will only allow letters
isAlphanumeric: true // will only allow alphanumeric characters, so "_abc" will fail
isNumeric: true // will only allow numbers
isInt: true, // checks for valid integers
isFloat: true, // checks for valid floating point numbers
isDecimal: true, // checks for any numbers
isLowercase: true, // checks for lowercase
isUppercase: true, // checks for uppercase
notNull: true, // won't allow null
isNull: true, // only allows null
notEmpty: true, // don't allow empty strings
equals: 'specific value', // only allow a specific value
contains: 'foo', // force specific substrings
notIn: [['foo', 'bar']], // check the value is not one of these
isIn: [['foo', 'bar']], // check the value is one of these
notContains: 'bar', // don't allow specific substrings
len: [2,10], // only allow values with length between 2 and 10
isUUID: 4, // only allow uuids
isDate: true, // only allow date strings
isAfter: "2011-11-05", // only allow date strings after a specific date
isBefore: "2011-11-05", // only allow date strings before a specific date
max: 23, // only allow values
Note that where multiple arguments need to be passed to the built-in validation
functions&comma; the arguments to be passed must be in an array&period; But if a single array
argument is to be passed&comma; for instance an array of acceptable strings for`isIn`&comma; this will be interpreted as multiple string arguments instead of one
array argument&period; To work around this pass a single-length array of arguments&comma;
such as`&lsqb;&lsqb;'one'&comma; 'two'&rsqb;&rsqb;`as shown above&period;
To use a custom error message instead of that provided by node-validator&comma; use an
object instead of the plain value or array of arguments&comma; for example a validator
which needs no argument can be given a custom message with
isInt: {
msg: "Must be an integer number of pennies"
}
or if arguments need to also be passed add an`args`property&colon;
isIn: {
args: [['en', 'zh']],
msg: "Must be English or Chinese"
}
When using custom validator functions the error message will be whatever message
the thrown`Error`object holds&period;
See [the node-validator project][4]for
more details on the built in validation methods&period;
**Hint&colon; **You can also define a custom function for the logging part&period; Just pass
a function&period; The first parameter will be the string that is logged&period;
#### Validators and`allowNull`
Since`v1&period;7&period;0`if a particular field of a model is set to allow null &lpar;with`allowNull&colon; true`&rpar; and that value has been set to`null`&comma; its validators do not
run&period; This means you can&comma; for instance&comma; have a string field which validates its
length to be at least 5 characters&comma; but which also allows`null`&period;
#### Model validations
Since`v1&period;7&period;0`&comma; validations can also be defined to check the model after the
field-specific validators&period; Using this you could&comma; for example&comma; ensure either
neither of`latitude`and`longitude`are set or both&comma; and
fail if one but not the other is set&period;
Model validator methods are called with the model object's context and are
deemed to fail if they throw an error&comma; otherwise pass&period; This is just the same as
with custom field-specific validators&period;
Any error messages collected are put in the validation result object alongside
the field validation errors&comma; with keys named after the failed validation
method's key in the`validate`option object&period; Even though there can only be one
error message for each model validation method at any one time&comma; it is presented
as a single string error in an array&comma; to maximize consistency with the field
errors&period; &lpar;Note that the structure of`validate&lpar;&rpar;`'s output is scheduled to change
in`v2&period;0`to avoid this awkward situation&period; In the mean time&comma; an error is issued
if a field exists with the same name as a custom model validation&period;&rpar;
An example&colon;
var Pub = Sequelize.define('Pub', {
name: { type: Sequelize.STRING },
address: { type: Sequelize.STRING },
latitude: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
validate: { min: -90, max: 90 }
},
longitude: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
validate: { min: -180, max: 180 }
},
}, {
validate: {
bothCoordsOrNone: function() {
if ((this.latitude === null) === (this.longitude === null)) {
throw new Error('Require either both latitude and longitude or neither')
}
}
}
})
In this simple case an object fails validation if latitude or longitude is
given&comma; but not both&period; If we try to build one with an out-of-range latitude and no
longitude&comma;`raging&UnderBar;bullock&UnderBar;arms&period;validate&lpar;&rpar;`might return
{
'latitude': ['Invalid number: latitude'],
'bothCoordsOrNone': ['Require either both latitude and longitude or neither']
}
### Configuration
You can also influence the way Sequelize handles your column names&colon;
var Bar = sequelize.define('Bar', { /* bla */ }, {
// don't add the timestamp attributes (updatedAt, createdAt)
timestamps: false,
 
// don't delete database entries but set the newly added attribute deletedAt
// to the current date (when deletion was done). paranoid will only work if
// timestamps are enabled
paranoid: true,
 
// don't use camelcase for automatically added attributes but underscore style
// so updatedAt will be updated_at
underscored: true,
 
// disable the modification of tablenames; By default, sequelize will automatically
// transform all passed model names (first parameter of define) into plural.
// if you don't want that, set the following
freezeTableName: true,
 
// define the table's name
tableName: 'my_very_custom_table_name'
})
If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:
var Foo = sequelize.define('Foo', { /* bla */ }, {
// don't forget to enable timestamps!
timestamps: true,
 
// I don't want createdAt
createdAt: false,
 
// I want updatedAt to actually be called updateTimestamp
updatedAt: 'updateTimestamp'
 
// And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
deletedAt: 'destroyTime',
paranoid: true
})
You can also change the database engine&comma; e&period;g&period; to MyISAM&period; InnoDB is default since`v1&period;2&period;1`of Sequelize&period;
var Person = sequelize.define('Person', { /* attributes */ }, {
engine: 'MYISAM'
})
 
// or globally
var sequelize = new Sequelize(db, user, pw, {
define: { engine: 'MYISAM' }
})
Finaly you can specify a comment for the table in MySQL and PG
var Person = sequelize.define('Person', { /* attributes */ }, {
comment: "I'm a table comment!"
})
### Import
You can also store your model definitions in a single file using the`import`-method&period; The returned object is exactly the same as defined in the imported file's function&period; Since`v1&period;5&period;0`of Sequelize the import is cached&comma; so you won't run into troubles when calling the import of a file twice or more often&period;
// in your server file - e.g. app.js
var Project = sequelize.import(__dirname + "/path/to/models/project")
 
// The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above
module.exports = function(sequelize, DataTypes) {
return sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}
Since`v1&period;7&period;0`the`import`-method can now accept a callback as an argument&period;
sequelize.import('Project', function(sequelize, DataTypes) {
return sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
})
### Database synchronization
When starting a new project you won't have a database structure and using Sequelize you won't need to&period; Just specify your model structures and let the library do the rest&period; Currently supported is the creation and deletion of tables&colon;
// Create the tables:
Project.sync() // will emit success or failure event
Task.sync() // will emit success or failure event
 
// Force the creation!
Project.sync({force: true}) // this will drop the table first and re-create it afterwards
 
// drop the tables:
Project.drop() // will emit success or failure event
Task.drop() // will emit success or failure event
 
// event handling:
Project.[sync|drop]().success(function() {
// ok ... everything is nice!
}).error(function(error) {
// oooh, did you entered wrong database credentials?
})
Because synchronizing and dropping all of your tables might be a lot of lines to write&comma; you can also let Sequelize do the work for you&colon;
// create all tables... now!
sequelize.sync() // will emit success or failure
 
// force it!
sequelize.sync({force: true}) // emit ... nomnomnom
 
// want to drop 'em all?
sequelize.drop() // I guess you've got it (emit)
 
// emit handling:
sequelize.[sync|drop]().success(function() {
// woot woot
}).error(function(error) {
// whooops
})
### Expansion of models
Sequelize allows you to pass custom methods to a model and it's instances&period; Just do the following&colon;
var Foo = sequelize.define('Foo', { /* attributes */}, {
classMethods: {
method1: function(){ return 'smth' }
},
instanceMethods: {
method2: function() { return 'foo' }
}
})
 
// Example:
Foo.method1()
Foo.build().method2()
Of course you can also access the instance's data and generate virtual getters&colon;
var User = sequelize.define('User', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, {
instanceMethods: {
getFullname: function() {
return [this.firstname, this.lastname].join(' ')
}
}
})
 
// Example:
User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
You can also set custom methods to all of your models during the instantiation&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
// Other options during the initialization could be here
define: {
classMethods: {
method1: function() {},
method2: function() {}
},
instanceMethods: {
method3: function() {}
}
}
})
 
// Example:
var Foo = sequelize.define('Foo', { /* attributes */});
Foo.method1()
Foo.method2()
Foo.build().method3()
### Data retrieval / Finders
Finder methods are designed to get data from the database&period; The returned data isn't just a plain object&comma; but instances of one of the defined classes&period; Check the next major chapter about instances for further information&period; But as those things are instances&comma; you can e&period;g&period; use the just describe expanded instance methods&period; So&comma; here is what you can do&colon;
#### find - Search for one specific element in the database
// search for known ids
Project.find(123).success(function(project) {
// project will be an instance of Project and stores the content of the table entry
// with id 123. if such an entry is not defined you will get null
})
 
// search for attributes
Project.find({ where: {title: 'aProject'} }).success(function(project) {
// project will be the first entry of the Projects table with the title 'aProject' || null
})
 
// since v1.3.0: only select some attributes and rename one
Project.find({
where: {title: 'aProject'},
attributes: ['id', ['name', 'title']]
}).success(function(project) {
// project will be the first entry of the Projects table with the title 'aProject' || null
// project.title will contain the name of the project
})
#### findOrCreate - Search for a specific element or create it if not available
The method`findOrCreate`can be used to check if a certain element is already existing in the database&period; If that is the case the method will result in a respective instance&period; If the element does not yet exist&comma; it will be created&period;
Let's assume we have an empty database with a`User`model which has a`username`and a`job`&period;
User
.findOrCreate({ username: 'sdepold' }, { job: 'Technical Lead JavaScript' })
.success(function(user, created) {
console.log(user.values)
console.log(created)
 
/*
{
username: 'sdepold',
job: 'Technical Lead JavaScript',
id: 1,
createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
}
created: true
*/
})
The code created a new instance&period;
So when we already have an instance &period;&period;&period;
User
.create({ username: 'fnord', job: 'omnomnom' })
.success(function() {
User
.findOrCreate({ username: 'fnord' }, { job: 'something else' })
.success(function(user, created) {
console.log(user.values)
console.log(created)
 
/*
{
username: 'fnord',
job: 'omnomnom',
id: 2,
createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
}
created: false
*/
})
})
&period;&period;&period; the existing entry will not be changed&period; See the`job`of the second user&comma; and the fact that created was false&period;
Notice that the success callback has two arguments. When using[promises][5]you should call`spread`[(API ref)][6]instead of`then`, since`then`will only recieve the first argument (the DAO), while`spread`will recieve both the DAO, and the`created`boolean.
#### findAndCountAll - Search for multiple elements in the database&comma; returns both data and total count
This is a convienience method that combines`findAll&lpar;&rpar;`and`count&lpar;&rpar;`&lpar;see below&rpar;&comma; this is useful when dealing with queries related to pagination
where you want to retrieve data with a`limit`and`offset`but also need to know the total number of records that match the query&period;
The success handler will always receive an object with to properties&colon;
* `count`- an integer&comma; total number records &lpar;matching the where clause&rpar;
* `rows`- an array of objects&comma; the records &lpar;matching the where clause&rpar; within the limit&sol;offset range
Project
.findAndCountAll({
where: ["title LIKE 'foo%'"],
offset: 10,
limit: 2
})
.success(function(result) {
console.log(result.count);
console.log(result.rows);
});
The options &lsqb;object&rsqb; that you pass to`findAndCountAll&lpar;&rpar;`is the same as for`findAll&lpar;&rpar;`&lpar;described below&rpar;&period;
#### findAll - Search for multiple elements in the database
// find multiple entries
Project.findAll().success(function(projects) {
// projects will be an array of all Project instances
})
 
// also possible:
Project.all().success(function(projects) {
// projects will be an array of all Project instances
})
 
// search for specific attributes - hash usage
Project.findAll({ where: { name: 'A Project' } }).success(function(projects) {
// projects will be an array of Project instances with the specified name
})
 
// search with string replacements
Project.findAll({ where: ["id > ?", 25] }).success(function(projects) {
// projects will be an array of Projects having a greater id than 25
})
 
// search within a specific range
Project.findAll({ where: { id: [1,2,3] } }).success(function(projects) {
// projects will be an array of Projects having the id 1, 2 or 3
// this is actually doing an IN query
})
 
// or
Project.findAll({ where: "name = 'A Project'" }).success(function(projects) {
// the difference between this and the usage of hashes (objects) is, that string usage
// is not sql injection safe. so make sure you know what you are doing!
})
 
// since v1.7.0 we can now improve our where searches
Project.findAll({
where: {
id: {
gt: 6, // id > 6
gte: 6, // id >= 6
lt: 10, // id < 10
lte: 10, // id
#### Complex filtering / OR queries
Since `v1.7.0-rc3`, it is possible to do complex where queries with
multiple levels of nested AND and OR conditions. In order to do that you
can use `Sequelize.or` and `Sequelize.and` and pass
an arbitrary amount of arguments to it. Every argument will get transformed
into a proper SQL condition and gets joined with the either `AND` or
`OR`.
Project.find({
where: Sequelize.and(
{ name: 'a project' },
Sequelize.or(
{ id: [1,2,3] },
{ id: { lt: 10 } }
)
)
})
This code will generate the following query:
SELECT *
FROM `Projects`
WHERE (
`Projects`.`name`='a project'
AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` < 10)
)
LIMIT 1
;
Notice, that instead of `Sequelize.and` you can also use a plain array
which will be treated as `Sequelize.and` if it contains
objects or hashes or other complex data types.
Furthermore you can use `Sequelize.or` as value for the where clause.
#### Manipulating the dataset with limit&comma; offset&comma; order and group
To get more relevant data&comma; you can use limit&comma; offset&comma; order and grouping&colon;
// limit the results of the query
Project.findAll({ limit: 10 })
 
// step over the first 10 elements
Project.findAll({ offset: 10 })
 
// step over the first 10 elements, and take 2
Project.findAll({ offset: 10, limit: 2 })
The syntax for grouping and ordering are equal&comma; so below it is only explained with a single example for group&comma; and the rest for order&period; Everything you see below can also be done for group
Project.findAll({order: 'title DESC'})
// yields ORDER BY title DESC
 
Project.findAll({group: 'name'})
// yields GROUP BY name
Notice how in the two examples above&comma; the string provided is inserted verbatim into the query&comma; i&period;e&period; column names are not escaped&period; When you provide a string to order &sol; group&comma; this will always be the case as per v 1&period;7&period;0&period; If you want to escape column names&comma; you should provide an array of arguments&comma; even though you only want to order &sol; group by a single column
something.find({
order: [
'name',
// will return `name`
'username DESC',
// will return `username DESC` -- i.e. don't do it!
['username', 'DESC'],
// will return `username` DESC
sequelize.fn('max', sequelize.col('age')),
// will return max(`age`)
[sequelize.fn('max', sequelize.col('age')), 'DESC'],
// will return max(`age`) DESC
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
// will return otherfunction(`col1`, 12, 'lalala') DESC
[sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
// will return otherfunction(awesomefunction(`col`)) DESC, This nesting is potentially infinite!
[{ raw: 'otherfunction(awesomefunction(`col`))' }, 'DESC']
// This won't be quoted, but direction will be added
]
})
To recap&comma; the elements of the order &sol; group array can be the following&colon;
* String - will be quoted
* Array - first element will be qouted&comma; second will be appended verbatim
* Object -
* Raw will be added verbatim without quoting
* Everything else is ignored&comma; and if raw is not set&comma; the query will fail
* Sequelize&period;fn and Sequelize&period;col returns functions and quoted cools
#### Raw queries
Sometimes you might be expecting a massive dataset that you just want to display&comma; without manipulation&period; For each row you select&comma; Sequelize creates a_DAO_&comma; with functions for update&comma; delete&comma; get associations etc&period; If you have thousands of rows&comma; this might take some time&period; If you only need the raw data and don't want to update anything&comma; you can do like this to get the raw data&period;
// Are you expecting a masssive dataset from the DB, and don't want to spend the time building DAOs for each entry?
// You can pass an extra query option to get the raw data instead:
Project.findAll({ where: ... }, { raw: true })
#### count - Count the occurences of elements in the database
There is also a method for counting database objects&colon;
Project.count().success(function(c) {
console.log("There are " + c + " projects!")
})
 
Project.count({ where: ["id > ?", 25] }).success(function(c) {
console.log("There are " + c + " projects with an id greater than 25.")
})
#### max - Get the greatest value of a specific attribute within a specific table
And here is a method for getting the max value of an attribute&colon;
/*
Let's assume 3 person objects with an attribute age.
The first one is 10 years old,
the second one is 5 years old,
the third one is 40 years old.
*/
Project.max('age').success(function(max) {
// this will return 40
})
 
Project.max('age', { where: { age: { lt: 20 } } }).success(function(max) {
// wil be 10
})
#### min - Get the least value of a specific attribute within a specific table
And here is a method for getting the min value of an attribute&colon;
/*
Let's assume 3 person objects with an attribute age.
The first one is 10 years old,
the second one is 5 years old,
the third one is 40 years old.
*/
Project.min('age').success(function(min) {
// this will return 5
})
 
Project.min('age', { where: { age: { gt: 5 } } }).success(function(min) {
// wil be 10
})
#### sum - Sum the value of specific attributes
In order to calculate the sum over a specific column of a table, you can
use the \`sum\` method.
/*
Let's assume 3 person objects with an attribute age.
The first one is 10 years old,
the second one is 5 years old,
the third one is 40 years old.
*/
Project.sum('age').success(function(sum) {
// this will return 55
})
 
Project.sum('age', { where: { age: { gt: 5 } } }).success(function(sum) {
// wil be 50
})
### Eager loading
When you are retrieving data from the database there is a fair chance that you also want to get their associations&period; This is possible since`v1&period;6&period;0`and is called eager loading&period; The basic idea behind that&comma; is the use of the attribute`include`when you are calling`find`or`findAll`&period; Lets assume the following setup&colon;
var User = sequelize.define('User', { name: Sequelize.STRING })
, Task = sequelize.define('Task', { name: Sequelize.STRING })
, Tool = sequelize.define('Tool', { name: Sequelize.STRING })
 
Task.belongsTo(User)
User.hasMany(Task)
User.hasMany(Tool, { as: 'Instruments' })
 
sequelize.sync().done(function() {
// this is where we continue ...
})
OK&period; So&comma; first of all&comma; let's load all tasks with their associated user&period;
Task.findAll({ include: [ User ] }).success(function(tasks) {
console.log(JSON.stringify(tasks))
 
/*
[{
"name": "A Task",
"id": 1,
"createdAt": "2013-03-20T20:31:40.000Z",
"updatedAt": "2013-03-20T20:31:40.000Z",
"UserId": 1,
"user": {
"name": "John Doe",
"id": 1,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z"
}
}]
*/
})
Notice that the accessor of the associated data is the name of the model in camelcase with lowercased first character&period; Also the accessor is singular as the association is one-to-something&period;
Next thing&colon; Loading of data with many-to-something associations&excl;
User.findAll({ include: [ Task ] }).success(function(users) {
console.log(JSON.stringify(users))
 
/*
[{
"name": "John Doe",
"id": 1,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z",
"tasks": [{
"name": "A Task",
"id": 1,
"createdAt": "2013-03-20T20:31:40.000Z",
"updatedAt": "2013-03-20T20:31:40.000Z",
"UserId": 1
}]
}]
*/
})
Notice that the accessor is plural&period; This is because the association is many-to-something&period;
If an association is aliased &lpar;using the`as`option&rpar;&comma; you_must_specify this alias when including the model&period; Notice how the user's`Tool`s are aliased as`Instruments`above&period; In order to get that right you have to specify the model you want to load&comma; as well as the alias&colon;
User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).success(function(users) {
console.log(JSON.stringify(users))
 
/*
[{
"name": "John Doe",
"id": 1,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z",
"instruments": [{
"name": "Toothpick",
"id": 1,
"createdAt": null,
"updatedAt": null,
"UserId": 1
}]
}]
*/
})
### Ordering Eager Loaded Associations
In the case of a one-to-many relationship.
Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
Company.findAll({
include: [ { model: Division, as: 'Div' } ],
order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
});
Company.findAll({
include: [ { model: Division, include: [ Department ] } ],
order: [ [ Division, Department, 'name' ] ]
});
In the case of many-to-many joins, you are also able to sort by attributes in the through table.
Company.findAll({
include: [ { model: Division, include: [ Department ] } ],
order: [ [ Division, DepartmentDivision, 'name' ] ]
});
### Nested eager loading
User.findAll({
include: [
{model: Tool, as: 'Instruments', include: [
{model: Teacher, include: [ /* etc */]}
]}
]
}).success(function(users) {
console.log(JSON.stringify(users))
 
/*
[{
"name": "John Doe",
"id": 1,
"createdAt": "2013-03-20T20:31:45.000Z",
"updatedAt": "2013-03-20T20:31:45.000Z",
"instruments": [{ // 1:M and N:M association
"name": "Toothpick",
"id": 1,
"createdAt": null,
"updatedAt": null,
"UserId": 1,
"Teacher": { // 1:1 association
"name": "Jimi Hendrix"
}
}]
}]
*/
})
**Final note&colon;**If you include an object which is not associated&comma; Sequelize will throw an error&period;
Tool.findAll({ include: [ User ] }).success(function(tools) {
console.log(JSON.stringify(tools))
})
 
// Error: User is not associated to Tool!
[0]: #configuration
[1]: https://github.com/epeli/underscore.string
[2]: #get_and_set_helper_funcs
[3]: https://github.com/chriso/validator.js
[4]: https://github.com/chriso/node-validator
[5]: /docs/latest/misc#asynchronicity
[6]: https://github.com/petkaantonov/bluebird/blob/master/API.md#spreadfunction-fulfilledhandler--function-rejectedhandler----promise
## Transactions
sequelize.transaction(function(t) {
// we just opened a new connection to the database which is transaction exclusive.
// also we send some first transaction queries to the database.
// do some async stuff ...
// if everything is ok ... commit the transaction
t.commit().success(function() {})
// if something failed ... rollback the transaction
t.rollback().success(function() {})
// the commit / rollback will emit events which can be observed via:
t.done(function() {
/* we will be here once the transaction
has been committed / reverted */
})
})
sequelize.transaction(function(t) {
User.create({ username: 'foo' }, { transaction: t }).success(function() {
// this user will only be available inside the session
User.all({ transaction: t }) // will return the user
User.all() // will not return the user
})
})
## Usage
### Basic usage
To get the ball rollin' you first have to create an instance of Sequelize&period; Use it the following way&colon;
var sequelize = new Sequelize('database', 'username'[, 'password'])
This will save the passed database credentials and provide all further methods&period; Furthermore you can specify a non-default host&sol;port&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
host: "my.server.tld",
port: 12345
})
If you just don't have a password&colon;
var sequelize = new Sequelize('database', 'username')
// or
var sequelize = new Sequelize('database', 'username', null)
You can also use a connection string&colon;
var sequelize = new Sequelize('mysql://user:pass@example.com:9821/dbname', {
// Look to the next section for possible options
})
### Options
Besides the host and the port&comma; Sequelize comes with a whole bunch of options&period; Here they are&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
// custom host; default: localhost
host: 'my.server.tld',
 
// custom port; default: 3306
port: 12345,
 
// custom protocol
// - default: 'tcp'
// - added in: v1.5.0
// - postgres only, useful for heroku
protocol: null,
 
// disable logging; default: console.log
logging: false,
 
// max concurrent database requests; default: 50
maxConcurrentQueries: 100,
 
// the sql dialect of the database
// - default is 'mysql'
// - currently supported: 'mysql', 'sqlite', 'postgres', 'mariadb'
dialect: 'mysql',
 
// you can also pass any dialect options to the underlying dialect library
// - default is empty
// - currently supported: 'mysql', 'mariadb'
dialectOptions: {
socketPath: '/Applications/MAMP/tmp/mysql/mysql.sock',
supportBigNumbers: true,
bigNumberStrings: true
},
 
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite',
 
// disable inserting undefined values as NULL
// - default: false
omitNull: true,
 
// a flag for using a native library or not.
// in the case of 'pg' -- set this to true will allow SSL support
// - default: false
native: true,
 
// Specify options, which are used when sequelize.define is called.
// The following example:
// define: {timestamps: false}
// is basically the same as:
// sequelize.define(name, attributes, { timestamps: false })
// so defining the timestamps for each model will be not necessary
// Below you can see the possible keys for settings. All of them are explained on this page
define: {
underscored: false
freezeTableName: false,
syncOnAssociation: true,
charset: 'utf8',
collate: 'utf8_general_ci',
classMethods: {method1: function() {}},
instanceMethods: {method2: function() {}},
timestamps: true
},
 
// similiar for sync: you can define this to always force sync for models
sync: { force: true },
 
// sync after each association (see below). If set to false, you need to sync manually after setting all associations. Default: true
syncOnAssociation: true,
 
// use pooling in order to reduce db connection overload and to increase speed
// currently only for mysql and postgresql (since v1.5.0)
pool: { maxConnections: 5, maxIdleTime: 30},
 
// language is used to determine how to translate words into singular or plural form based on the [lingo project](https://github.com/visionmedia/lingo)
// options are: en [default], es
language: 'en'
})
**Hint&colon;** You can also define a custom function for the logging part&period; Just pass a function&period; The first parameter will be the string that is logged&period;
### Read replication
Sequelize supports read replication&comma; i&period;e&period; having multiple servers that you can connect to when you want to do a SELECT query&period; When you do read replication&comma; you specify one or more servers to act as read replicas&comma; and one server to act as the write master&comma; which handles all writes and updates and propagates them to the replicas &lpar;note that the actual replication process is**not **handled by Sequelize&comma; but should be set up in MySql&rpar;&period;
var sequelize = new Sequelize('database', null, null, {
dialect: 'mysql',
port: 3306
replication: {
read: [
{ host: '8.8.8.8', username: 'anotherusernamethanroot', password: 'lolcats!' },
{ host: 'localhost', username: 'root', password: null }
],
write: { host: 'localhost', username: 'root', password: null }
},
pool: { // If you want to override the options used for the read pool you can do so here
maxConnections: 20,
maxIdleTime: 30000
},
})
If you have any general settings that apply to all replicas you do not need to provide them for each instance&period; In the code above&comma; database name and port is propagated to all replicas&period; The same will happen for user and password&comma; if you leave them out for any of the replicas&period; Each replica has the following options&colon;`host`&comma;`port`&comma;`username`&comma;`password`&comma;`database`
Sequelize uses a pool to manage connections to your replicas&period; The default options are&colon;
{
maxConnections: 10,
minConnections: 0,
maxIdleTime: 1000
}
If you want to modify these&comma; you can pass pool as an options when instantiating Sequelize&comma; as shown above&period;
**Note&colon;** Read replication only works for MySQL at the moment&excl;
### Dialects
With the release of Sequelize`v1&period;6&period;0`&comma; the library got independent from specific dialects&period; This means&comma; that you'll have to add the respective connector library to your project yourself. Version 1.7.0 stable has been released in bundles with the connector libraries (sequelize-mysql, sequelize-postgres etc.) but these bundles are not maintained, and will not be released for 2.0.0 upwards.
#### MySQL
In order to get Sequelize working nicely together with MySQL&comma; you'll need to install`mysql&commat;~2&period;0&period;0-alpha7`or higher&period; Once that's done you can use it like this&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
// mysql is the default dialect, but you know...
// for demo purporses we are defining it nevertheless :)
// so: we want mysql!
dialect: 'mysql'
})
**Note:** You can pass options directly to dialect library by setting the
`dialectOptions` parameter. See [Options][0]
for examples (currently only mysql and mariadb are supported).
#### MariaDB
For MariaDB compatibility you have to install the package `mariasql@0.1.20`, or higher.
The configuration needs to look like this:
var sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mariadb'
})
#### SQLite
For SQLite compatibility you'll need`sqlite3&commat;~2&period;1&period;5`&period; Configure Sequelize like this&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
// sqlite! now!
dialect: 'sqlite',
 
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite'
})
#### PostgreSQL
The library for PostgreSQL is`pg&commat;~2&period;0&period;0`&period; You'll just need to define the dialect&colon;
var sequelize = new Sequelize('database', 'username', 'password', {
// gimme postgres, please!
dialect: 'postgres'
})
### Executing raw SQL queries
As there are often use cases in which it is just easier to execute raw &sol; already prepared SQL queries&comma; you can utilize the function`sequelize&period;query`&period;
Here is how it works&colon;
// Arguments for raw queries
sequelize.query('your query', [, callee], [, options], [, replacements])
// Quick example
sequelize.query("SELECT * FROM myTable").success(function(myTableRows) {
console.log(myTableRows)
})
// Callee is the model definition. This allows you to easily map a query
// to a predefined model for sequelizejs e.g:
sequelize
.query('SELECT * FROM projects', Projects)
.success(function(projects){
// Each record will now be mapped to the project's DAO-Factory.
console.log(projects)
})
// Options is an object with the following keys:
sequelize
.query('SELECT 1', null, {
// A function (or false) for logging your queries
// Will get called for every SQL query that gets send
// to the server.
logging: console.log,
// If plain is true, then sequelize will only return the first
// record of the result set. In case of false it will all records.
plain: false,
// Set this to true if you don't have a model definition for your query.
raw: false
})
// Note the second argument being null!
// Even if we declared a callee here, the raw: true would
// supersede and return a raw object.
sequelize
.query('SELECT * FROM projects', null, { raw: true })
.success(function(projects) {
console.log(projects)
})
Replacements in a query can be done in two different ways, either using
named parameters (starting with `:`), or unnamed, represented by a ?
The syntax used depends on the fourth argument passed to the function:
* If an array is passed, `?` will be replaced in the order that they appear in the array
* If an object is passed, `:key` will be replaced with the keys from that object.
If the object contains keys not found in the query or vice verca, an exception
will be thrown.
sequelize
.query(
'SELECT * FROM projects WHERE status = ?', null,
{ raw: true }, ['active']
)
.success(function(projects) {
console.log(projects)
})
sequelize
.query(
'SELECT * FROM projects WHERE status = :status ', null,
{ raw: true }, { status: 'active' }
)
.success(function(projects) {
console.log(projects)
})
**One note:** If the attribute names of the table contain dots, the resulting objects will be nested:
sequelize.query('select 1 as `foo.bar.baz`').success(function(rows) {
console.log(JSON.stringify(rows))
/*
[{
"foo": {
"bar": {
"baz": 1
}
}
}]
*/
})
[0]: /docs/latest/usage#options
## Utils
Sequelize comes with some handy utils including references to`lodash`as well as some individual helpers&period; You can access them via`Sequelize&period;Utils`&period;
### Lodash.js
You can access all the methods of lodash like this&colon;
Sequelize.Utils._.each(/* ... */)
Sequelize.Utils._.map(/* ... */)
Sequelize.Utils._...
Also Sequelize ships the Underscore extension`underscore&period;string`&comma; which allows nifty string manipulation&colon;
Sequelize.Utils._.camelize('something') // Something
Check out the page of [Lodash][0]&comma; [Underscore][1] and [underscore&period;string][2] for further information&period;
### QueryChainer
Because you will want to save&sol;create&sol;delete several items at once and just go on after all of them are saved&comma; Sequelize provides the`QueryChainer`module&period; It can be used like this&colon;
var chainer = new Sequelize.Utils.QueryChainer
chainer.add(/* Query | EventEmitter */)
chainer.run().success(function(){}).error(function(errors){})
And a real world example&colon;
var chainer = new Sequelize.Utils.QueryChainer
var Task = sequelize.define('Task', /* ... */)
 
chainer
.add(Task.drop())
.add(Task.sync())
 
for(var i = 0; i < 20; i++)
chainer.add(Task.create({}))
 
chainer
.run()
.success(function(){})
.error(function(errors){})
It is also possible to force a serial run of the query chainer by using the following syntax:
new Sequelize.Utils.QueryChainer()
.add(Model, 'function', [param1, param2])
.add(Model, 'function2', [param1, param2])
.runSerially()
.success(function() { /* no problems :) */ })
.error(function(err) { /* hmm not good :> */ })
 
// and with options:
 
new Sequelize.Utils.QueryChainer()
.add(Model, 'function', [param1, param2], {
// Will be executed before Model#function is called
before: function(model) {},
 
/*
Will be executed after Model#function was called
and the function emitted a success or error event.
If the following success option is passed, the function
will be executed after the success function.
*/
after: function(migration) {},
 
// Will be executed if Model#function emits a success event.
success: function(migration, callback) {}
})
// skipOnError: don't execute functions once one has emitted an failure event.
.runSerially({ skipOnError: true })
.success(function() { /* no problems :) */ })
.error(function(err) { /* hmm not good :> */ })
If the success callbacks of the added methods are passing values&comma; they can be utilized in the actual`success`method of the query chainer&colon;
chainer.add(Project.getTasks())
chainer.add(Project.getTeam())
chainer.run().success(function(results){
var tasks = results[0]
var team = results[1]
})
### CustomEventEmitter
One of the core components of the library is the `CustomEventEmitter`,
which takes an (asynchronous) function, allows the binding to certain events
and finally runs the passed function. Within the function, the user gets
access to the emitter instance and can (once the function's logic is done)
emit success / error events. The basic look is the following:
new Sequelize.Utils.CustomEventEmitter(function(emitter) {
doAsyncLogic(function(err) {
if (err) {
emitter.emit('error', err)
} else {
emitter.emit('success')
}
})
})
.success(function() { /* success! */ })
.error(function(err) { /* error */ })
.run()
As you can probably see, the event observing is the very same
as for all the asynchronous methods in the Sequelize universe.
That's because every asynchronouse function in Sequelize
returns an instance of the CustomEventEmitter.
If you are afraid, that the passed function might have been
executed already just before you bound the event observers:
The execution of the function is delayed minimally.
Because of that you can also just call `.run()`
and bind the events afterwards.
Because there is a fair chance, that you already have an emitter
and you just want to pipe the events from one emitter to the other,
each instance has a method called `.proxy()`:
new Sequelize.Utils.CustomEventEmitter(function(emitter) {
asyncAuthLogic(function(err) {
if (err) {
return emitter.emit('err')
}
 
Model
.find()
.proxy(emitter, { events: ['error'] })
.success(function(result) {
emitter.emit('success', parseInt(result.stringifiedAge, 10))
})
})
})
.error(function(err) { console.log(err) })
.success(function(ageAsInteger) { console.log(ageAsInteger) })
.run()
In this example we first do an asynchronous authentication check,
receive an instance from the database afterwards and finally
transform its data. As we aren't interested in a special treatment
for the different error case, we will just observe the error event
once and pipe the error cases of the `Model.find()` call
to the outer emitter.
[0]: http://lodash.com/
[1]: http://underscorejs.org/
[2]: https://github.com/epeli/underscore.string
No preview for this file type
# Imprint - Boring legal stuff for the rest of us.
As there are people who are suing for fun and glory, you can find the respective information about the author of the page right here. Have fun reading ...
## AUTHOR(S)
```
Main author:
Sascha Depold
Uhlandstr. 122
10717 Berlin
sascha [at] depold [dot] com
```
## INHALTLICHE VERANTWORTUNG
```
Ich übernehme keine Haftung für ausgehende Links.
Daher musst du dich bei Problemen an deren Betreiber wenden!
```
\ No newline at end of file
The Sequelize library provides easy access to MySQL, MariaDB, SQLite or PostgreSQL databases by mapping database entries to objects and vice versa. To put it in a nutshell, it's an ORM (Object-Relational-Mapper). The library is written entirely in JavaScript and can be used in the Node.JS environment.
## Easy installation
```bash
$ npm install sequelize
$ npm install mysql
```
## Simple usage
```js
var Sequelize = require('sequelize')
, sequelize = new Sequelize('database', 'username', 'password')
var User = sequelize.define('User', {
username: Sequelize.STRING,
birthday: Sequelize.DATE
})
sequelize.sync().success(function() {
User.create({
username: 'sdepold',
birthday: new Date(1986, 06, 28)
}).success(function(sdepold) {
console.log(sdepold.values)
})
})
```
## Trusted and used by
[![](/images/shutterstock.png)](docs/misc#shutterstock)
[![](/images/clevertech.png)](docs/misc#clevertech)
[![](/images/metamarkets.png)](docs/misc#metamarkets)
[![](/images/filsh.png)](docs/misc#filsh)
(c) Sascha Depold, [et al.](https://github.com/sequelize/sequelize-doc/graphs/contributors) 2006 - 2014 [Imprint](imprint)
\ No newline at end of file
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block htmltitle %}
<title>{{ page_title }}</title>
{% endblock %}
{# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="{{ base_url }}/css/theme.css" type="text/css" />
{%- for path in extra_css %}
<link href="{{ path }}" rel="stylesheet">
{%- endfor %}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
<script src="{{ base_url }}/js/theme.js"></script>
{%- for path in extra_javascript %}
<script src="{{ path }}"></script>
{%- endfor %}
<style>
body {font-size: 90%;}
pre, code {font-size: 100%;}
h3, h4, h5, h6 {color: #2980b9; font-weight: 300}
</style>
{%- block extrahead %} {% endblock %}
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
{# SIDE NAV, TOGGLES ON MOBILE #}
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-nav-search">
<a href="{{ homepage_url }}" class="icon icon-home"> {{ site_name }}</a>
{% include "searchbox.html" %}
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
{% include "toc.html" %}
</div>
&nbsp;
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="icon icon-reorder"></i>
<a href="{{ homepage_url }}">{{ project }}</a>
</nav>
{# PAGE CONTENT #}
<div class="wy-nav-content">
<div class="rst-content">
{% include "breadcrumbs.html" %}
<div role="main">
<div class="section">
{{ content }}
</div>
</div>
{%- block footer %}
{% include "footer.html" %}
{% endblock %}
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" style="cursor: pointer">
<span class="rst-current-version" data-toggle="rst-current-version">
{% if repo_name == 'GitHub' %}
<a class="icon icon-github" style="float: left; color: #fcfcfc"> GitHub</a>
{% elif repo_name == 'Bitbucket' %}
<a class="icon icon-bitbucket" style="float: left; color: #fcfcfc"> BitBucket</a>
{% endif %}
<span><a href="" style="color: #fcfcfc;">&laquo; Previous</a></span>
<span style="margin-left: 15px"><a href="" style="color: #fcfcfc">Next &raquo;</a></span>
</span>
</div>
</body>
</html>
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="{{ homepage_url }}">Docs</a> &raquo;</li>
<li>{{ current_page.title }}</li>
<li class="wy-breadcrumbs-aside">
{% if repo_url %}
{% if repo_name == 'GitHub' %}
<a href="{{ repo_url }}" class="icon icon-github"> Edit on GitHub</a>
{% elif repo_name == 'Bitbucket' %}
<a href="{{ repo_url }}" class="icon icon-bitbucket"> Edit on BitBucket</a>
{% endif %}
{% endif %}
</li>
</ul>
<hr/>
</div>
*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:20px 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,.rst-content tt,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.font-smooth,.icon:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-tag-input-group .wy-tag .wy-tag-remove:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-tag-input-group,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:fontawesome-webfont;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#fontawesome-webfont") format("svg")}.icon:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-tag-input-group .wy-tag .wy-tag-remove:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before{display:inline-block;font-family:fontawesome-webfont;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .icon,a .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success a .wy-input-context,a .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger a .wy-input-context,a .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning a .wy-input-context,a .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info a .wy-input-context,a .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag a .wy-tag-remove,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink{display:inline-block;text-decoration:inherit}.icon-large:before{vertical-align:-10%;font-size:1.33333em}.btn .icon,.btn .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .wy-input-context,.btn .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .btn .wy-tag-remove,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.nav .icon,.nav .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .wy-input-context,.nav .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .nav .wy-tag-remove,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink{display:inline}.btn .icon.icon-large,.btn .wy-inline-validate.wy-inline-validate-success .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .icon-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .icon-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .icon-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .icon-large.wy-input-context,.btn .wy-tag-input-group .wy-tag .icon-large.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .icon-large.wy-tag-remove,.btn .rst-content .icon-large.admonition-title,.rst-content .btn .icon-large.admonition-title,.btn .rst-content h1 .icon-large.headerlink,.rst-content h1 .btn .icon-large.headerlink,.btn .rst-content h2 .icon-large.headerlink,.rst-content h2 .btn .icon-large.headerlink,.btn .rst-content h3 .icon-large.headerlink,.rst-content h3 .btn .icon-large.headerlink,.btn .rst-content h4 .icon-large.headerlink,.rst-content h4 .btn .icon-large.headerlink,.btn .rst-content h5 .icon-large.headerlink,.rst-content h5 .btn .icon-large.headerlink,.btn .rst-content h6 .icon-large.headerlink,.rst-content h6 .btn .icon-large.headerlink,.btn .rst-content dl dt .icon-large.headerlink,.rst-content dl dt .btn .icon-large.headerlink,.nav .icon.icon-large,.nav .wy-inline-validate.wy-inline-validate-success .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .icon-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .icon-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .icon-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .icon-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .icon-large.wy-input-context,.nav .wy-tag-input-group .wy-tag .icon-large.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .icon-large.wy-tag-remove,.nav .rst-content .icon-large.admonition-title,.rst-content .nav .icon-large.admonition-title,.nav .rst-content h1 .icon-large.headerlink,.rst-content h1 .nav .icon-large.headerlink,.nav .rst-content h2 .icon-large.headerlink,.rst-content h2 .nav .icon-large.headerlink,.nav .rst-content h3 .icon-large.headerlink,.rst-content h3 .nav .icon-large.headerlink,.nav .rst-content h4 .icon-large.headerlink,.rst-content h4 .nav .icon-large.headerlink,.nav .rst-content h5 .icon-large.headerlink,.rst-content h5 .nav .icon-large.headerlink,.nav .rst-content h6 .icon-large.headerlink,.rst-content h6 .nav .icon-large.headerlink,.nav .rst-content dl dt .icon-large.headerlink,.rst-content dl dt .nav .icon-large.headerlink{line-height:0.9em}.btn .icon.icon-spin,.btn .wy-inline-validate.wy-inline-validate-success .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .icon-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .icon-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .icon-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .icon-spin.wy-input-context,.btn .wy-tag-input-group .wy-tag .icon-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .icon-spin.wy-tag-remove,.btn .rst-content .icon-spin.admonition-title,.rst-content .btn .icon-spin.admonition-title,.btn .rst-content h1 .icon-spin.headerlink,.rst-content h1 .btn .icon-spin.headerlink,.btn .rst-content h2 .icon-spin.headerlink,.rst-content h2 .btn .icon-spin.headerlink,.btn .rst-content h3 .icon-spin.headerlink,.rst-content h3 .btn .icon-spin.headerlink,.btn .rst-content h4 .icon-spin.headerlink,.rst-content h4 .btn .icon-spin.headerlink,.btn .rst-content h5 .icon-spin.headerlink,.rst-content h5 .btn .icon-spin.headerlink,.btn .rst-content h6 .icon-spin.headerlink,.rst-content h6 .btn .icon-spin.headerlink,.btn .rst-content dl dt .icon-spin.headerlink,.rst-content dl dt .btn .icon-spin.headerlink,.nav .icon.icon-spin,.nav .wy-inline-validate.wy-inline-validate-success .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .icon-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .icon-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .icon-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .icon-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .icon-spin.wy-input-context,.nav .wy-tag-input-group .wy-tag .icon-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .icon-spin.wy-tag-remove,.nav .rst-content .icon-spin.admonition-title,.rst-content .nav .icon-spin.admonition-title,.nav .rst-content h1 .icon-spin.headerlink,.rst-content h1 .nav .icon-spin.headerlink,.nav .rst-content h2 .icon-spin.headerlink,.rst-content h2 .nav .icon-spin.headerlink,.nav .rst-content h3 .icon-spin.headerlink,.rst-content h3 .nav .icon-spin.headerlink,.nav .rst-content h4 .icon-spin.headerlink,.rst-content h4 .nav .icon-spin.headerlink,.nav .rst-content h5 .icon-spin.headerlink,.rst-content h5 .nav .icon-spin.headerlink,.nav .rst-content h6 .icon-spin.headerlink,.rst-content h6 .nav .icon-spin.headerlink,.nav .rst-content dl dt .icon-spin.headerlink,.rst-content dl dt .nav .icon-spin.headerlink{display:inline-block}.btn.icon:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.icon:hover:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:hover:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before{opacity:1}.btn-mini .icon:before,.btn-mini .wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn-mini .wy-input-context:before,.btn-mini .wy-tag-input-group .wy-tag .wy-tag-remove:before,.wy-tag-input-group .wy-tag .btn-mini .wy-tag-remove:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before{font-size:14px;vertical-align:-15%}li .icon,li .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success li .wy-input-context,li .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger li .wy-input-context,li .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning li .wy-input-context,li .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info li .wy-input-context,li .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag li .wy-tag-remove,li .rst-content .admonition-title,.rst-content li .admonition-title,li .rst-content h1 .headerlink,.rst-content h1 li .headerlink,li .rst-content h2 .headerlink,.rst-content h2 li .headerlink,li .rst-content h3 .headerlink,.rst-content h3 li .headerlink,li .rst-content h4 .headerlink,.rst-content h4 li .headerlink,li .rst-content h5 .headerlink,.rst-content h5 li .headerlink,li .rst-content h6 .headerlink,.rst-content h6 li .headerlink,li .rst-content dl dt .headerlink,.rst-content dl dt li .headerlink{display:inline-block}li .icon-large:before,li .icon-large:before{width:1.875em}ul.icons{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.icons li .icon,ul.icons li .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success ul.icons li .wy-input-context,ul.icons li .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger ul.icons li .wy-input-context,ul.icons li .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning ul.icons li .wy-input-context,ul.icons li .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info ul.icons li .wy-input-context,ul.icons li .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag ul.icons li .wy-tag-remove,ul.icons li .rst-content .admonition-title,.rst-content ul.icons li .admonition-title,ul.icons li .rst-content h1 .headerlink,.rst-content h1 ul.icons li .headerlink,ul.icons li .rst-content h2 .headerlink,.rst-content h2 ul.icons li .headerlink,ul.icons li .rst-content h3 .headerlink,.rst-content h3 ul.icons li .headerlink,ul.icons li .rst-content h4 .headerlink,.rst-content h4 ul.icons li .headerlink,ul.icons li .rst-content h5 .headerlink,.rst-content h5 ul.icons li .headerlink,ul.icons li .rst-content h6 .headerlink,.rst-content h6 ul.icons li .headerlink,ul.icons li .rst-content dl dt .headerlink,.rst-content dl dt ul.icons li .headerlink{width:0.8em}ul.icons li .icon-large:before,ul.icons li .icon-large:before{vertical-align:baseline}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope-alt:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before,.wy-tag-input-group .wy-tag .wy-tag-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-power-off:before,.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-gear:before,.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file-alt:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-rotate-right:before,.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-mail-forward:before,.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-gears:before,.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up-alt:before{content:"\f087"}.icon-thumbs-down-alt:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-unchecked:before,.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-rotate-left:before,.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"\f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-text-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}.icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-mail-reply:before,.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}.icon-expand-alt:before{content:"\f116"}.icon-collapse-alt:before{content:"\f117"}.icon-smile:before{content:"\f118"}.icon-frown:before{content:"\f119"}.icon-meh:before{content:"\f11a"}.icon-gamepad:before{content:"\f11b"}.icon-keyboard:before{content:"\f11c"}.icon-flag-alt:before{content:"\f11d"}.icon-flag-checkered:before{content:"\f11e"}.icon-terminal:before{content:"\f120"}.icon-code:before{content:"\f121"}.icon-reply-all:before{content:"\f122"}.icon-mail-reply-all:before{content:"\f122"}.icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123"}.icon-location-arrow:before{content:"\f124"}.icon-crop:before{content:"\f125"}.icon-code-fork:before{content:"\f126"}.icon-unlink:before{content:"\f127"}.icon-question:before{content:"\f128"}.icon-info:before{content:"\f129"}.icon-exclamation:before{content:"\f12a"}.icon-superscript:before{content:"\f12b"}.icon-subscript:before{content:"\f12c"}.icon-eraser:before{content:"\f12d"}.icon-puzzle-piece:before{content:"\f12e"}.icon-microphone:before{content:"\f130"}.icon-microphone-off:before{content:"\f131"}.icon-shield:before{content:"\f132"}.icon-calendar-empty:before{content:"\f133"}.icon-fire-extinguisher:before{content:"\f134"}.icon-rocket:before{content:"\f135"}.icon-maxcdn:before{content:"\f136"}.icon-chevron-sign-left:before{content:"\f137"}.icon-chevron-sign-right:before{content:"\f138"}.icon-chevron-sign-up:before{content:"\f139"}.icon-chevron-sign-down:before{content:"\f13a"}.icon-html5:before{content:"\f13b"}.icon-css3:before{content:"\f13c"}.icon-anchor:before{content:"\f13d"}.icon-unlock-alt:before{content:"\f13e"}.icon-bullseye:before{content:"\f140"}.icon-ellipsis-horizontal:before{content:"\f141"}.icon-ellipsis-vertical:before{content:"\f142"}.icon-rss-sign:before{content:"\f143"}.icon-play-sign:before{content:"\f144"}.icon-ticket:before{content:"\f145"}.icon-minus-sign-alt:before{content:"\f146"}.icon-check-minus:before{content:"\f147"}.icon-level-up:before{content:"\f148"}.icon-level-down:before{content:"\f149"}.icon-check-sign:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:"\f14a"}.icon-edit-sign:before{content:"\f14b"}.icon-external-link-sign:before{content:"\f14c"}.icon-share-sign:before{content:"\f14d"}.icon-compass:before{content:"\f14e"}.icon-collapse:before{content:"\f150"}.icon-collapse-top:before{content:"\f151"}.icon-expand:before{content:"\f152"}.icon-euro:before,.icon-eur:before{content:"\f153"}.icon-gbp:before{content:"\f154"}.icon-dollar:before,.icon-usd:before{content:"\f155"}.icon-rupee:before,.icon-inr:before{content:"\f156"}.icon-yen:before,.icon-jpy:before{content:"\f157"}.icon-renminbi:before,.icon-cny:before{content:"\f158"}.icon-won:before,.icon-krw:before{content:"\f159"}.icon-bitcoin:before,.icon-btc:before{content:"\f15a"}.icon-file:before{content:"\f15b"}.icon-file-text:before{content:"\f15c"}.icon-sort-by-alphabet:before{content:"\f15d"}.icon-sort-by-alphabet-alt:before{content:"\f15e"}.icon-sort-by-attributes:before{content:"\f160"}.icon-sort-by-attributes-alt:before{content:"\f161"}.icon-sort-by-order:before{content:"\f162"}.icon-sort-by-order-alt:before{content:"\f163"}.icon-thumbs-up:before{content:"\f164"}.icon-thumbs-down:before{content:"\f165"}.icon-youtube-sign:before{content:"\f166"}.icon-youtube:before{content:"\f167"}.icon-xing:before{content:"\f168"}.icon-xing-sign:before{content:"\f169"}.icon-youtube-play:before{content:"\f16a"}.icon-dropbox:before{content:"\f16b"}.icon-stackexchange:before{content:"\f16c"}.icon-instagram:before{content:"\f16d"}.icon-flickr:before{content:"\f16e"}.icon-adn:before{content:"\f170"}.icon-bitbucket:before{content:"\f171"}.icon-bitbucket-sign:before{content:"\f172"}.icon-tumblr:before{content:"\f173"}.icon-tumblr-sign:before{content:"\f174"}.icon-long-arrow-down:before{content:"\f175"}.icon-long-arrow-up:before{content:"\f176"}.icon-long-arrow-left:before{content:"\f177"}.icon-long-arrow-right:before{content:"\f178"}.icon-apple:before{content:"\f179"}.icon-windows:before{content:"\f17a"}.icon-android:before{content:"\f17b"}.icon-linux:before{content:"\f17c"}.icon-dribbble:before{content:"\f17d"}.icon-skype:before{content:"\f17e"}.icon-foursquare:before{content:"\f180"}.icon-trello:before{content:"\f181"}.icon-female:before{content:"\f182"}.icon-male:before{content:"\f183"}.icon-gittip:before{content:"\f184"}.icon-sun:before{content:"\f185"}.icon-moon:before{content:"\f186"}.icon-archive:before{content:"\f187"}.icon-bug:before{content:"\f188"}.icon-vk:before{content:"\f189"}.icon-weibo:before{content:"\f18a"}.icon-renren:before{content:"\f18b"}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso{padding:12px;line-height:24px;margin-bottom:24px}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:transparent;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso{background:#f3f6f6}.wy-alert.wy-alert-neutral strong,.rst-content .wy-alert-neutral.note strong,.rst-content .wy-alert-neutral.attention strong,.rst-content .wy-alert-neutral.caution strong,.rst-content .wy-alert-neutral.danger strong,.rst-content .wy-alert-neutral.error strong,.rst-content .wy-alert-neutral.hint strong,.rst-content .wy-alert-neutral.important strong,.rst-content .wy-alert-neutral.tip strong,.rst-content .wy-alert-neutral.warning strong,.rst-content .wy-alert-neutral.seealso strong{color:#404040}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a{color:#2980b9}.wy-tray-container{position:fixed;top:-50px;left:0;width:100%;-webkit-transition:top 0.2s ease-in;-moz-transition:top 0.2s ease-in;transition:top 0.2s ease-in}.wy-tray-container.on{top:0}.wy-tray-container li{display:none;width:100%;background:#343131;padding:12px 24px;color:#fff;margin-bottom:6px;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1),0px -1px 2px -1px rgba(255,255,255,0.5) inset}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.btn{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:100%;padding:6px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);border-bottom:solid 3px rgba(0,0,0,0.1);background-color:#27ae60;text-decoration:none;font-weight:500;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear;outline-none:false}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;color:#fff;outline:0}.btn:active{border-top:solid 3px rgba(0,0,0,0.1);border-bottom:solid 1px rgba(0,0,0,0.1);box-shadow:0px 1px 2px -1px rgba(0,0,0,0.5) inset}.btn[disabled]{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-danger{background-color:#e74c3c !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#e67e22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#343131}.btn-invert:hover{background-color:#413d3d !important}.btn-link{background-color:transparent !important;color:#2980b9;border-color:transparent}.btn-link:hover{background-color:transparent !important;color:#409ad5;border-color:transparent}.btn-link:active{background-color:transparent !important;border-color:transparent;border-top:solid 1px transparent;border-bottom:solid 3px transparent}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown:hover .wy-dropdown-menu{display:block}.wy-dropdown .caret:after{font-family:fontawesome-webfont;content:"\f0d7";font-size:70%}.wy-dropdown-menu{position:absolute;top:100%;left:0;display:none;float:left;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:0.5em 1em 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:0.5em}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#999;font-size:90%}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button{-webkit-appearance:button;cursor:pointer;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#2980b9}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#f3f6f6;color:#cad2d3}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#e9322d}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:0.8em;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fff;color:#cad2d3;border-color:transparent}.wy-checkbox,.wy-radio{margin:0.5em 0;color:#404040 !important;display:block}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{padding:6px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.wy-control-group{margin-bottom:24px;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 2px #e74c3c}.wy-control-group.wy-control-group-error textarea{border:solid 2px #e74c3c}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#ccc;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-tag-input-group{padding:4px 4px 0px 4px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;background:#fff;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}.wy-tag-input-group .wy-tag{display:inline-block;background-color:rgba(0,0,0,0.1);padding:0.5em 0.625em;border-radius:2px;position:relative;margin-bottom:4px}.wy-tag-input-group .wy-tag .wy-tag-remove{color:#ccc;margin-left:5px}.wy-tag-input-group .wy-tag .wy-tag-remove:hover{color:#e74c3c}.wy-tag-input-group label{margin-left:5px;display:inline-block;margin-bottom:0}.wy-tag-input-group input{border:none;font-size:100%;margin-bottom:4px;box-shadow:none}.wy-form-upload{border:solid 1px #ccc;border-bottom:solid 3px #ccc;background-color:#fff;padding:24px;display:inline-block;text-align:center;cursor:pointer;color:#404040;-webkit-transition:border-color 0.1s ease-in;-moz-transition:border-color 0.1s ease-in;transition:border-color 0.1s ease-in;*zoom:1}.wy-form-upload:before,.wy-form-upload:after{display:table;content:""}.wy-form-upload:after{clear:both}@media screen and (max-width: 480px){.wy-form-upload{width:100%}}.wy-form-upload .image-drop{display:none}.wy-form-upload .image-desktop{display:none}.wy-form-upload .image-loading{display:none}.wy-form-upload .wy-form-upload-icon{display:block;font-size:32px;color:#b3b3b3}.wy-form-upload .image-drop .wy-form-upload-icon{color:#27ae60}.wy-form-upload p{font-size:90%}.wy-form-upload .wy-form-upload-image{float:left;margin-right:24px}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-image{width:100%;margin-bottom:24px}}.wy-form-upload img{max-width:125px;max-height:125px;opacity:0.9;-webkit-transition:opacity 0.1s ease-in;-moz-transition:opacity 0.1s ease-in;transition:opacity 0.1s ease-in}.wy-form-upload .wy-form-upload-content{float:left}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-content{width:100%}}.wy-form-upload:hover{border-color:#b3b3b3;color:#404040}.wy-form-upload:hover .image-desktop{display:block}.wy-form-upload:hover .image-drag{display:none}.wy-form-upload:hover img{opacity:1}.wy-form-upload:active{border-top:solid 3px #ccc;border-bottom:solid 1px #ccc}.wy-form-upload.wy-form-upload-big{width:100%;text-align:center;padding:72px}.wy-form-upload.wy-form-upload-big .wy-form-upload-content{float:none}.wy-form-upload.wy-form-upload-file p{margin-bottom:0}.wy-form-upload.wy-form-upload-file .wy-form-upload-icon{display:inline-block;font-size:inherit}.wy-form-upload.wy-form-upload-drop{background-color:#ddf7e8}.wy-form-upload.wy-form-upload-drop .image-drop{display:block}.wy-form-upload.wy-form-upload-drop .image-desktop{display:none}.wy-form-upload.wy-form-upload-drop .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-desktop{display:none}.wy-form-upload.wy-form-upload-loading .image-loading{display:block}.wy-form-upload.wy-form-upload-loading .wy-input-prefix{display:none}.wy-form-upload.wy-form-upload-loading p{margin-bottom:0}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}.wy-form-gallery-manage{margin-left:-12px;margin-right:-12px}.wy-form-gallery-manage li{float:left;padding:12px;width:20%;cursor:pointer}@media screen and (max-width: 768px){.rst-content{margin-top: 65px;}.wy-nav-top{display:block;position:fixed;width:100%;}.wy-form-gallery-manage li{width:25%}}@media screen and (max-width: 480px){.wy-form-gallery-manage li{width:50%}}.wy-form-gallery-manage li:active{cursor:move}.wy-form-gallery-manage li>a{padding:12px;background-color:#fff;border:solid 1px #e1e4e5;border-bottom:solid 3px #e1e4e5;display:inline-block;-webkit-transition:all 0.1s ease-in;-moz-transition:all 0.1s ease-in;transition:all 0.1s ease-in}.wy-form-gallery-manage li>a:active{border:solid 1px #ccc;border-top:solid 3px #ccc}.wy-form-gallery-manage img{width:100%;-webkit-transition:all 0.05s ease-in;-moz-transition:all 0.05s ease-in;transition:all 0.05s ease-in}li.wy-form-gallery-edit{position:relative;color:#fff;padding:24px;width:100%;display:block;background-color:#343131;border-radius:4px}li.wy-form-gallery-edit .arrow{position:absolute;display:block;top:-50px;left:50%;margin-left:-25px;z-index:500;height:0;width:0;border-color:transparent;border-style:solid;border-width:25px;border-bottom-color:#343131}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-controls{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:0.2em 0 0.8em}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-grid-one-col{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:1066px;margin-top:1.618em}.wy-grid-one-col:before,.wy-grid-one-col:after{display:table;content:""}.wy-grid-one-col:after{clear:both}.wy-grid-one-col section{display:block;float:left;margin-right:2.35765%;width:100%;background:#fcfcfc;padding:1.618em;margin-right:0}.wy-grid-one-col section:last-child{margin-right:0}.wy-grid-index-card{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:460px;margin-top:1.618em;background:#fcfcfc;padding:1.618em}.wy-grid-index-card:before,.wy-grid-index-card:after{display:table;content:""}.wy-grid-index-card:after{clear:both}.wy-grid-index-card header,.wy-grid-index-card section,.wy-grid-index-card aside{display:block;float:left;margin-right:2.35765%;width:100%}.wy-grid-index-card header:last-child,.wy-grid-index-card section:last-child,.wy-grid-index-card aside:last-child{margin-right:0}.wy-grid-index-card.twocol{max-width:768px}.wy-grid-index-card.twocol section{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol section:last-child{margin-right:0}.wy-grid-index-card.twocol aside{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol aside:last-child{margin-right:0}.wy-grid-search-filter{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;margin-bottom:24px}.wy-grid-search-filter:before,.wy-grid-search-filter:after{display:table;content:""}.wy-grid-search-filter:after{clear:both}.wy-grid-search-filter .wy-grid-search-filter-input{display:block;float:left;margin-right:2.35765%;width:74.41059%}.wy-grid-search-filter .wy-grid-search-filter-input:last-child{margin-right:0}.wy-grid-search-filter .wy-grid-search-filter-btn{display:block;float:left;margin-right:2.35765%;width:23.23176%}.wy-grid-search-filter .wy-grid-search-filter-btn:last-child{margin-right:0}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px;margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}a{color:#2980b9;text-decoration:none}a:hover{color:#3091d1}.link-danger{color:#e74c3c}.link-danger:hover{color:#d62c1a}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}small{font-size:80%}pre,.rst-content tt{max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:10px;font-family:"Incosolata","Consolata","Monaco",monospace;color:#e74c3c;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.full-width{width:100%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li{list-style:square}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li{list-style:decimal;margin-left:24px}.wy-type-large{font-size:120%}.wy-type-normal{font-size:100%}.wy-type-small{font-size:100%}.wy-type-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980b9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27ae60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#e74c3c !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9b59b6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,.rst-content .literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}pre.literal-block{@extends .codeblock;}@media print{.codeblock,.rst-content .literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#eaf2f5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#2980b9;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980b9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:absolute;top:0;left:0;width:300px;overflow:hidden;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}nav.stickynav{position:fixed;top:0}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .rst-versions .rst-current-version .wy-tag-remove,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink{color:#fcfcfc}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content .section>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after{visibility:visible;content:"\f0c1";font-family:fontawesome-webfont;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt{color:#000}.rst-content tt big,.rst-content tt em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt{font-weight:bold}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.wy-menu-vertical span.toctree-l0{display:inline-block;line-height:18px;padding:0.4045em 1.318em;display:block;position:relative;font-size:80%;color:#838383}
\ No newline at end of file
This diff could not be displayed because it is too large.
<footer>
{% if next_page or previous_page %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% if next_page %}
<a href="{{ next_page.url }}" class="btn btn-neutral float-right" title="{{ next_page.title }}"/>Next <span class="icon icon-circle-arrow-right"></span></a>
{% endif %}
{% if previous_page %}
<a href="{{ previous_page.url }}" class="btn btn-neutral" title="{{ previous_page.title }}"><span class="icon icon-circle-arrow-left"></span> Previous</a>
{% endif %}
</div>
{% endif %}
<hr/>
<div role="contentinfo">
<p>
<!-- Copyright etc -->
</p>
</div>
Built with <a href="http://www.mkdocs.org">MkDocs</a>, using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
No preview for this file type
$( document ).ready(function() {
// Shift nav in mobile when clicking the menu.
$(document).on('click', "[data-toggle='wy-nav-top']", function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
// Close menu when you click a link.
$(document).on('click', ".wy-menu-vertical .current ul li a", function() {
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
$(document).on('click', "[data-toggle='rst-current-version']", function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up");
});
// Make tables responsive
$("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>");
});
window.SphinxRtdTheme = (function (jquery) {
var stickyNav = (function () {
var navBar,
win,
stickyNavCssClass = 'stickynav',
applyStickNav = function () {
if (navBar.height() <= win.height()) {
navBar.addClass(stickyNavCssClass);
} else {
navBar.removeClass(stickyNavCssClass);
}
},
enable = function () {
applyStickNav();
win.on('resize', applyStickNav);
},
init = function () {
navBar = jquery('nav.wy-nav-side:first');
win = jquery(window);
};
jquery(init);
return {
enable : enable
};
}());
return {
StickyNav : stickyNav
};
}($));
{#
basic/search.html
~~~~~~~~~~~~~~~~~
Template for the search page.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block extrahead %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script type="text/javascript" id="searchindexloader"></script>
{{ super() }}
{% endblock %}
{% block body %}
<noscript>
<div id="fallback" class="admonition warning">
<p class="last">
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
</p>
</div>
</noscript>
{% if search_performed %}
<h2>{{ _('Search Results') }}</h2>
{% if not search_results %}
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
{% endif %}
{% endif %}
<div id="search-results">
{% if search_results %}
<ul>
{% for href, caption, context in search_results %}
<li>
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
<p class="context">{{ context|e }}</p>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock %}
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<ul class="current">
{% for nav_item in nav %}
{% if nav_item.children %}
<span class="toctree-l0">{{ nav_item.title }}</span>
{% for nav_item in nav_item.children %}
<li class="toctree-l1 {% if nav_item.active%}current{%endif%}">
<a class="{% if nav_item.active%}current{%endif%}" href="{{ nav_item.url }}">{{ nav_item.title }}</a>
{% if nav_item == current_page %}
<ul>
{% for toc_item in toc %}
<li class="toctree-l2"><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% for toc_item in toc_item.children %}
<li><a class="toctree-l3" href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% endfor %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
{% else %}
<li class="toctree-l1 {% if nav_item.active%}current{%endif%}">
<a class="{% if nav_item.active%}current{%endif%}" href="{{ nav_item.url }}">{{ nav_item.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
git+https://github.com/dart-lang/py-gfm.git
site_name: Sequelize - node.js ORM for Postgres, MySQl, MariaDB and SQLite
theme_dir: docs/readthedocs_theme
repo_url: https://github.com/sequelize/sequelize
site_favicon: favicon.ico
markdown_extensions: [gfm]
extra_css:
- css/custom.css
extra_javascript:
- //cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js
pages:
- ['index.md', 'Home', 'Welcome']
- ['imprint.md', 'Home', 'Imprint']
- ['articles/getting-started.md', 'Articles', 'Getting started']
- ['articles/heroku.md', 'Articles', 'Heroku']
- ['articles/express.md', 'Articles', 'Usage with Express.JS']
- ['docs/installation.md', 'Docs', 'Installation']
- ['docs/usage.md', 'Docs', 'Usage']
- ['docs/models.md', 'Docs', 'Models']
- ['docs/instances.md', 'Docs', 'Instances']
- ['docs/associations.md', 'Docs', 'Associations']
- ['docs/hooks.md', 'Docs', 'Hooks']
- ['docs/transactions.md', 'Docs', 'Transactions']
- ['docs/migrations.md', 'Docs', 'Migrations']
- ['docs/misc.md', 'Docs', 'Misc']
- ['docs/utils.md', 'Docs', 'Utils']
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!