Django Multi Tenancy

What is the best solution for multi tenancy in Django?

There's several things you're asking here. 1: how to model relationships between models, 2: how to display a view for a single company

For problem one, Django handles problems like this in data modeling with relationships. Here's the documentation tutorial for relationships: https://docs.djangoproject.com/en/dev/topics/db/models/#relationships

In your example, a Property to Company relationship is 'many-to-one', meaning that a Company has many Properties but a Property has only one Company. In Django(the link I gave you) all that is typically done is a foreign key in the model that is the 'many', or in your case Property. Here's what I would do:

class Property(models.Model):
owner = models.ForeignKey(Company)

This also allows you to query relationships, solving the second problem.

If I have a Company c, I can access all the Properties associated with it like this:

c.property_set.all()
# => [Property <MyProperty>, Property <OtherProperty>, ...]

That's a query you would do in the view and then pass to the template.

Here's a Django-provided example of this very thing(many-to-one) that you may find useful: https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_one/.

optimal architecture for multitenant application on django

We built a multitenancy platform using the following architecture. I hope you can find some useful hints.

  • Each tenant gets sub-domain (t1.example.com)
  • Using url rewriting the requests for the Django application are rewritten to something like example.com/t1
  • All url definitions are prefixed with something like (r'^(?P<tenant_id>[\w\-]+)
  • A middleware processes and consumes the tenant_id and adds it to the request (e.g. request.tenant = 't1')
  • Now you have the current tenant available in each view without specifying the tenant_id argument every view
  • In some cases you don't have the request available. I solved this issue by binding the tenant_id to the current thread (similar to the current language using threading.local )
  • Create decorators (e.g a tenant aware login_required), middlewares or factories to protect views and select the right models
  • Regarding to the databases I used two different scenarios:

    • Setup multiple databases and configure a routing according to current tenant. I used this first but switched to one database after about one year. The reasons were the following:

      • We didn't need a high secure solution to separate the data
      • The different tenants used almost all the same models
      • We had to manage a lot of databases (and didn't built an easy update/migration process)
    • Use one database with some simple mapping tables for i.e. users and different models. To add additional and tenant specific model fields we use model inheritance.

Regarding the environment we use the following setup:

  • Nginx
  • uWSGI
  • PostgreSQL
  • Memcached

From my point of view this setup has the following pro's and con's:

Pro:

  • One application instance knowing the current tenant
  • Most parts of the project don't have to bother with tenant specific issues
  • Easy solution for sharing entities between all tenants (e.g. messages)

Contra:

  • One quite large database
  • Some very similar tables due to the model inheritance
  • Not secured on the database layer

Of course the best architecture strongly depends on your requirements as number of tenants, the delta of your models, security requirements and so on.

Update: As we reviewed our architecture, I suggest to not rewrite the URL as indicated in point 2-3. I think a better solutions is to put the tenant_id as a Request Header and extract (point 4) the tenant_id out of the request with something like request.META.get('TENANT_ID', None). This way you get neutral URLs and it's much easier to use Django built-in functions (e.g. {% url ...%} or reverse()) or external apps.

Suggestion for Approachs to Develop Multi tenant Django Proj on Google App Engine

Today Google released SDK 1.3.6, which includes multi-tenancy baked right into the solution.

http://googleappengine.blogspot.com/2010/08/multi-tenancy-support-high-performance_17.html



Related Topics



Leave a reply



Submit