Multiple deployment of a django project with separate configurations

Hi all,

We have been developing a relatively large Django project for several customers. The core of the project, consisting in several Django apps, is the same for all customers. Each customer can add views, model classes to several of the project apps. Each customer version is deployed on its own server, with its own database - so we are not looking at a multiple tenant solution.

While we had few customers, we managed this by symlinking files and subdirectories of the Django project to customer directories. We use a structure that looks like this (simplified):

├── config
|   ├── settings.py -> ../customer_config/settings.py
|   ├── urls.py
|   └── uwsgi.py
├── app1
|   ├── migrations -> ../customer_config/app1/migrations
│   ├── models
|   │   ├── customer -> ../../customer_config/app1/models
│   │   └── models.py
│   ├── templates
│   ├── admin.py -> ../customer_config/app1/admin.py
│   ├── urls.py
│   └── views.py
├── app2
|   └── ...
├── frontend
|   ├── js
|   └── css
|       ├── customer -> ../../customer_config/assets/css
|       └── index.scss
├── customer_config -> ../customer/a
└── customer
    ├── a
    |   ├── settings.py
    |   ├── assets
    |   |   └── css
    |   |       └── customer.scss
    |   ├── app1
    |   |   ├── admin.py
    |   |   ├── migrations
    |   |   └── models
    |   └── app2
    |       ├── urls.py
    |       └── views
    └── b
        └── ...

When we want to switch customer, we simply rewrite the customer_config -> ../customer/a link.

This works well, but we would now like to split git repositories, and keep one repository for the core Django project, and one for each customer configuration. Ideally, we’d set the core Django project as a git submodule, called in each of the customer repo. However, the core project is not really completely standalone, as it calls on customer-specific code.

What do you think would be the best approach for this?
Thanks !

<opinion>
There’s probably not one “best” approach here, but a handful of options that all have tradeoffs.
</opinion>

I can share with you what we do - our situation is similar. We have had 6 clients each using an instance of our software. (It’s deployed on our servers that we manage, the clients don’t get the code.) This may not be of any use to you - our situations may be different enough that it wouldn’t work in your environment.

All the core code is contained in one primary set of apps. (The core project consists of 4 key apps and some lesser apps.)

Each client’s individualization is contained in an app for that client. We also maintain settings files for each client, along with client-specific data fixtures for updating reference tables for that client.
(There’s a lot of our system that is internally data-driven. For example, each client instance has their own logo files. There’s a row in a model identifying which logo to use on pages - this would be what gets customized for each client.)

So while every deployment contains all the code, only the core code and client-specific code is active for any one deployment.

As a result of this organization, everything is maintained in one repo. This has worked well for us for more than 5 years now.

Thanks a lot for your answer.

Indeed, we seem to have similar architectures, although our core and customer apps might not be as cleanly decoupled as yours.

What I’d like though would be to have separate repos, to cleanly separate core code from customer code. Among other benefits, this would allow using different releases of the core application for different customers. Right now, when we make a change to the core application, we de facto upgrade every customer, which is good in a way, but creates the need to make sure that all customers versions still work.

Given our small number of customers, this is not strictly necessary, but it would make our life easier.

I would consider this to be a bad thing. Once you start changing the “core” for a customer, you no longer have a core component. Five different deployments with five different versions means five different versions of the so-called-core that you’re trying to support. You could even find yourself in a situation down the road where you’ve got two different clients with conflicting requirements - one in which there is no clean way to implement them for both if you’re trying to straddle this fence.

This makes it an architectural decision, not a technical decision. Either way will work - both have their advantages, but it’s a decision you’ll want to make consciously. Either recognize that you’re managing “n” versions, or, manage a core, but ensure that everyone is always running on the common core.