Installation/Usage

Requirements

This application requires, and depends upon Django being installed. Only Django 1.7 and above is supported, but if you are still using 1.7 then you really should upgrade!

Postgres is required to allow schema to be used. psycopg2 or psycopg2cffi is required as per normal Django/Postgres integration.

Installation and Configuration

Install it using your favourite installer: mine is pip:

pip install django-boardinghouse

You will need to add boardinghouse to your settings.INSTALLED_APPS.

You will need to use the provided database engine in your settings.DATABASES:

'boardinghouse.backends.postgres'

You will need to add the provided middleware to your settings.MIDDLEWARE_CLASSES:

'boardinghouse.middleware.SchemaMiddleware'

You will probably also want to install the context processor:

'boardinghouse.context_processors.schemata'

Where this needs to go depends on your version of django: in 1.8 and newer it goes in settings.TEMPLATES...['context_processors']. In older versions, it goes in settings.TEMPLATE_CONTEXT_PROCESSORS.

If you have the admin installed, it adds a column to the admin django.contrib.admin.models.LogEntry class, to store the object schema when applicable.

It’s probably much easier to start using django-boardinghouse right from the beginning of a project: trying to split an existing database may be possible, but is not supported at this stage.

Usage

Schema Model

By default, the model boardinghouse.models.Schema will be used for the object representing the schemata, however you may override this by using the setting settings.BOARDINGHOUSE_SCHEMA_MODEL. You’ll probably want to subclass boardinghouse.models.AbstractSchema.

Shared Models

Some models are required by the system to be shared: these can be seen in:

boardinghouse.schema.REQUIRED_SHARED_MODELS = ['auth.user', 'auth.permission', 'auth.group', 'boardinghouse.schema', 'sites.site', 'sessions.session', 'contenttypes.contenttype', 'admin.logentry', 'migrations.migration', <django.utils.functional.__proxy__ object at 0x7f9430522450>, <django.utils.functional.__proxy__ object at 0x7f9430522710>]

These models are required to be shared by the system.

Other shared classes must subclass boardinghouse.base.SharedSchemaModel, or mixin boardinghouse.base.SharedSchemaMixin. This is required because the migration creation code will not pick up the _is_shared_model attribute, and will attempt to create the table in all schemata.

If a model is listed in the settings.SHARED_MODELS list, then it is deemed to be a shared model. This is how you can define that a 3rd-party application’s models should be shared.

If a model contains only foreign keys to other models (and possibly a primary key), then this model will be shared if all linked-to models are shared (or any of the above conditions are true).

All other models are deemed to be schema-specific models, and will be put into each schema that is created.

Management commands

When django-boardinghouse has been installed, it will override the following commands:

boardinghouse.management.commands.loaddata

This replaces the loaddata command with one that takes a new option: --schema. This is required when non-shared-models are included in the file(s) to be loaded, and the schema with this name will be used as a target.

boardinghouse.management.commands.dumpdata

Replaces the dumpdata command.

If the --schema option is supplied, that schema is used for the source of the data. If it is not supplied, then the __template__ schema will be used (which will not contain any data).

If any models are supplied as arguments (using the app_label.model_name notation) that are not shared models, it is an error to fail to pass a schema.

Middleware

The included middleware must be installed:

class boardinghouse.middleware.SchemaMiddleware(get_response=None)[source]

Middleware to set the postgres schema for the current request’s session.

The schema that will be used is stored in the session. A lookup will occur (but this could easily be cached) on each request.

There are three ways to change the schema as part of a request.

  1. Request a page with a querystring containg a __schema value:

    https://example.com/page/?__schema=<schema-name>
    

The schema will be changed (or cleared, if this user cannot view that schema), and the page will be re-loaded (if it was a GET). This method of changing schema allows you to have a link that changes the current schema and then loads the data with the new schema active.

It is used within the admin for having a link to data from an arbitrary schema in the LogEntry history.

This type of schema change request should not be done with a POST request.

  1. Add a request header:

    X-Change-Schema: <schema-name>
    
This will not cause a redirect to the same page without query string. It is the only way to do a schema change within a POST request, but could be used for any request type.
  1. Use a specific request:

    https://example.com/__change_schema__/<schema-name>/
    
This is designed to be used from AJAX requests, or as part of an API call, as it returns a status code (and a short message) about the schema change request. If you were storing local data, and did one of these, you are probably going to have to invalidate much of that.

You could also come up with other methods.

Template Variables

You will probably want to install the context processor: this will ensure that there is always a context variable schemata.

boardinghouse.context_processors.schemata(request)[source]

A Django context_processor that provides access to the logged-in user’s visible schemata, and selected schema.

Adds the following variables to the context:

schemata: all available schemata this user has schema_choices: (schema, name) pairs of available schemata selected_schema: the currenly selected schema name

Changing Schema

As outlined in Middleware, there are three ways to change the schema: a __schema querystring, a request header and a specific request.

These all work without any required additions to your urls.py.