Orator 0.8 is now out. This version brings several improvements, notably for global scopes, and fixes.

For the full list of changes, see the CHANGELOG


Global scopes improvements

Global scopes are now easier to use. Global scopes now only require the apply() method and can be used directly without the need to create a mixin. Also a simple function can be used as a global scope.

Using a scope directly

from orator import Scope

class ActiveScope(Scope):

    def apply(self, builder, model):
        return builder.where('active', 1)

Using a callable

class User(Model):

    def _boot(cls):
        cls.add_global_scope('active_scope', lambda query: query.where('active', 1))

        cls.add_global_scope(lambda query: query.order_by('name'))

        super(User, cls)._boot()

A @scope decorator to define query scopes

In previous versions of Orator a query scope was defined by defining a method prefixed by scope_:

class User(Model):

    def scope_popular(self, query):
        return query.where('votes', '>', 100)

    def scope_of_type(self, query, type):
        return query.where_type(type)

users = User.popular().of_type('member').get()

Now, you can use the @scope decorator:

from orator.orm import scope

class User(Model):

    def popular(self, query):
        return query.where('votes', '>', 100)

    def of_type(self, query, type):
        return query.where_type(type)

Support for default values

Orator now supports default values on models with the __attributes__ attribute:

class User(Model):

    __attributes__ = {
        'active': True

Support for only one timestamp column on models

Orator now supports maintaining only one timestamp column, like so:

class User(Model):

    __timestamps__ = ['created_at']

Support for extra conditions on relationships

If you want to apply permanent query conditions on your relationships you can now do so by returning a Builder instance instead of a Model subclass.

For example, let's say you want all comments of a user to be ordered by date of creation in descending order:

class User(Model):

    def comments(self):
        return Comment.order_by('created_at', 'desc')

Schema Builder

Support for a use_current() on timestamps

When defining timestamp columns you can now specify that the default value should be the current timestamp using the use_current() method:

with self.schema.table('users') as table:

You can also pass the use_current keyword argument to the timestamps() method:

with self.schema.table('users') as table:


New make:model command

The make:model command creates a new Model class.

# Create a new ./models/user.py file
orator make:model User

# Create a new ./models/user.py file and a migration file
orator make:model User -m

New commands names

Most commands have been renamed to be more consistent:

  • migrations:install becomes migrate:install.
  • migrations:make becomes make:migration.
  • migrations:refresh becomes migrate:refresh.
  • migrations:reset becomes migrate:reset.
  • migrations:rollback becomes migrate:rollback.
  • migrations:run becomes migrate.
  • seeders:make becomes make:seed.
  • migrations:install becomes migrate:install.


Support for unicode by default

For MySQL and PostgreSQL, the connectors are configured to return unicode strings. If you want to use the previous behavior just set the use_unicode configuration option to False.

Other improvements and fixes



  • Fixes Model.get_foreign_key() method
  • Fixes soft deletes
  • Avoid going through __setattr__ method when setting timestamps

Schema Builder

  • #33 [SQLite] Renaming or dropping columns loses NULL constraint
  • #32 [SQLite] Renaming or dropping columns fails when columns' name is a keyword
  • #31 [SQLite] Changing columns loses default column values.

Query Builder

  • Fixes query grammar default columns value


  • Fixing Connection._try_again_if_caused_by_lost_connection() not being called
  • Preventing default connection being set to None
  • Fixing json type behavior for Postgres


  • Fixing migration stubs


Schema builder

  • Improving dbal to support SQLite fully.
  • Improving fluents

Query Builder

  • #28 Making where_in() method accept Collection instances


  • Improves how queries are run in Connection class


  • Adds flatten() method to Collection class
View Comments