Nous avons construit un système de multilocation plateforme en utilisant l'architecture suivante. J'espère que vous y trouverez des conseils utiles.
- Chaque locataire obtient un sous-domaine (t1.example.com).
- En utilisant la réécriture d'url, les requêtes pour l'application Django sont réécrites en quelque chose comme exemple.com/t1.
- Toutes les définitions d'url sont préfixées par quelque chose comme
(r'^(?P<tenant_id>[\w\-]+)
- A intergiciel traite et consomme le tenant_id et l'ajoute à la demande (par exemple, request.tenant = 't1')
- Maintenant vous avez le locataire actuel disponible dans chaque vue sans spécifier l'argument tenant_id dans chaque vue.
- Dans certains cas, vous ne disposez pas de la demande. J'ai résolu ce problème en liant le tenant_id au thread en cours (de manière similaire à la fonction langue actuelle en utilisant
threading.local
)
- Créer des décorateurs (par exemple un locataire conscient)
login_required
), des middlewares ou des factories pour protéger les vues et sélectionner les bons modèles
- En ce qui concerne les bases de données, j'ai utilisé deux scénarios différents :
- Installer plusieurs bases de données et configurer un routage selon le locataire actuel. J'ai d'abord utilisé ce système, mais je suis passé à une seule base de données après environ un an. Les raisons étaient les suivantes :
- Nous n'avions pas besoin d'une solution hautement sécurisée pour séparer les données.
- Les différents locataires ont utilisé presque tous les mêmes modèles
- Nous devions gérer un grand nombre de bases de données (et n'avions pas mis en place un processus de mise à jour/migration facile).
- Utiliser une base de données avec quelques tables de correspondance simples, par exemple pour les utilisateurs et les différents modèles. Pour ajouter des champs supplémentaires et spécifiques au modèle du locataire, nous utilisons la méthode suivante l'héritage du modèle .
En ce qui concerne l'environnement, nous utilisons la configuration suivante :
De mon point de vue, cette configuration présente les avantages et les inconvénients suivants :
Pro :
- Une instance d'application connaissant le locataire actuel
- La plupart des parties du projet ne doivent pas s'occuper de questions spécifiques aux locataires.
- Solution facile pour partager des entités entre tous les locataires (par exemple, des messages)
Contra :
- Une base de données assez importante
- Certains tableaux très similaires en raison de l'héritage du modèle
- Non sécurisé au niveau de la couche de base de données
Bien sûr, la meilleure architecture dépend fortement de vos besoins, comme le nombre de locataires, le delta de vos modèles, les exigences de sécurité, etc.
Mise à jour : Comme nous avons revu notre architecture, je suggère de no réécrire l'URL comme indiqué au point 2-3. Je pense qu'une meilleure solution est de mettre le tenant_id
en tant qu'en-tête de la demande et extraire (point 4) l'en-tête de la demande. tenant_id
de la demande avec quelque chose comme request.META.get('TENANT_ID', None)
. De cette façon, vous obtenez des URLs neutres et il est beaucoup plus facile d'utiliser les fonctions intégrées de Django (par exemple {% url ...%}
o reverse()
) ou des applications externes.