Multi-Tenancy ist ein Ansatz, der es einer Django-Anwendung ermöglicht, mehreren Kunden oder Mandanten gleichzeitig zu dienen, wobei jeder Mandant seine eigenen isolierten Daten hat. In Django bedeutet Multi-Tenancy, dass Du eine Anwendung erstellen kannst, die verschiedene Benutzergruppen oder Organisationen unterstützt, ohne dass deren Daten vermischt werden.
In diesem Artikel zeige ich Dir, wie Multi-Tenancy in Django funktioniert. Wir betrachten zwei gängige Ansätze: die schema-basierte Trennung und die row-basierte Trennung. Zusätzlich gibt es Beispiele zur Implementierung und wichtige Best Practices.
Es gibt zwei Hauptansätze: die schema-basierte und die row-basierte Trennung.
Bei der schema-basierten Trennung hat jeder Mandant sein eigenes Datenbankschema. Dies ermöglicht eine vollständige Datenisolation. Django unterstützt dies mit Paketen wie django-tenant-schemas
und django-tenants
, die für jeden Mandanten ein eigenes Schema anlegen und verwalten.
Hierbei wird ein zusätzliches Feld wie mandant_id
in jede Tabelle eingefügt. Jeder Eintrag ist einem Mandanten zugeordnet. Django filtert automatisch alle Abfragen so, dass nur die Daten des aktuellen Mandanten angezeigt werden. Diese Methode ist einfacher umzusetzen und funktioniert mit jeder relationalen Datenbank, kann jedoch bei vielen Datensätzen die Performance beeinträchtigen.
django-tenant-schemas
Die schema-basierte Trennung bietet eine starke Isolation und ist ideal, wenn Du eine große Anzahl an Mandanten unterstützen musst. Zunächst installierst Du django-tenant-schemas
und passt die Konfiguration in Django an, damit für jeden Mandanten ein eigenes Schema angelegt wird.
pip install django-tenant-schemas
In settings.py
definierst Du DATABASES
so, dass django-tenant-schemas
verwendet wird. Beachte, dass dieses Paket nur mit PostgreSQL funktioniert.
DATABASES = {
'default': {
'ENGINE': 'tenant_schemas.postgresql_backend',
'NAME': 'multi_tenant_db',
'USER': 'dbuser',
'PASSWORD': 'dbpassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
Nun muss noch die Middleware und die Datenbank-Router in der settings.py
angepasst werden ...
MIDDLEWARE_CLASSES = (
'tenant_schemas.middleware.TenantMiddleware',
#...
)
DATABASE_ROUTERS = (
'tenant_schemas.routers.TenantSyncRouter',
)
... und die App in den INSTALLED_APPs
vor allen anderen Apps eingetragen werden:
INSTALLED_APPs = [
"tenant_schemas",
...
]
Jetzt erstellt du eine neue App:
python manage.py startapp customers
und erstellst ein Client-Model:
# models.py
from django.db import models
from tenant_schemas.models import TenantMixin
class Client(TenantMixin):
name = models.CharField(max_length=100)
paid_until = models.DateField()
on_trial = models.BooleanField()
created_on = models.DateField(auto_now_add=True)
mache das Model in den settings bekannt:
TENANT_MODEL = "customers.Client"
Führe anschließend Migrationen durch, um die Schema-Struktur in der Datenbank zu erstellen.
python manage.py migrate_schemas --shared
Du kannst jetzt für jeden neuen Mandanten ein eigenes Schema anlegen und Domain-spezifische Einstellungen vornehmen.
from customers.models import Client
# create your public tenant
tenant = Client(domain_url='tenant.my-domain.com',
schema_name='tenant1',
name='My First Tenant',
paid_until='2014-12-05',
on_trial=True)
tenant.save()
Der row-basierte Ansatz nutzt ein zusätzliches Feld mandant_id
in den Datenbanktabellen, um die Daten verschiedenen Mandanten zuzuordnen. Dieser Ansatz funktioniert mit jeder relationalen Datenbank und ist einfacher einzurichten.
Erstelle ein Mandantenmodell, um jeden Mandanten in der Anwendung eindeutig zu identifizieren.
from django.db import models
class Mandant(models.Model):
name = models.CharField(max_length=100)
erstellungsdatum = models.DateField(auto_now_add=True)
Füge dann das mandant
-Feld in Modellen hinzu, die mandantenspezifische Daten speichern sollen.
from django.db import models
class Projekt(models.Model):
mandant = models.ForeignKey(Mandant, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
beschreibung = models.TextField()
Um sicherzustellen, dass nur die Daten des aktuellen Mandanten abgerufen werden, kannst Du einen benutzerdefinierten Manager verwenden.
class ProjektManager(models.Manager):
def fuer_mandant(self, mandant):
return self.filter(mandant=mandant)
Weise diesen benutzerdefinierten Manager dem Modell zu und verwende ihn in Views, um mandantenspezifische Daten abzufragen.
class Projekt(models.Model):
mandant = models.ForeignKey(Mandant, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
beschreibung = models.TextField()
objects = ProjektManager()
In der View nutzt Du fuer_mandant
, um nur Projekte des aktuellen Mandanten abzurufen:
def projekt_liste(request):
mandant = request.user.mandant
projekte = Projekt.objects.fuer_mandant(mandant)
return render(request, 'projekte.html', {'projekte': projekte})
Diese Lösung ermöglicht es Dir, Daten gezielt für den jeweiligen Mandanten zu laden, ohne dass andere Daten geladen werden müssen.
Die Wahl zwischen schema- und row-basierter Trennung hängt von den Anforderungen Deiner Anwendung ab. Die schema-basierte Trennung bietet eine hohe Sicherheit und Skalierbarkeit, benötigt jedoch PostgreSQL und ist komplexer einzurichten. Die row-basierte Trennung funktioniert mit jeder relationalen Datenbank und ist schneller einzurichten, aber bei großen Datenmengen weniger effizient.
Verwende schema-basierte Trennung für Anwendungen mit vielen Mandanten und hohem Sicherheitsbedarf. Die row-basierte Trennung eignet sich gut für kleinere Anwendungen oder Anwendungen mit geringem Datenvolumen.
Beachte bei Multi-Tenancy-Projekten einige wichtige Punkte, um die Anwendung sicher und effizient zu gestalten.
Trenne mandantenspezifische Konfigurationen deutlich vom allgemeinen Code, um eine spätere Wartung und Skalierung zu erleichtern.
Achte bei der row-basierten Trennung darauf, Datenintegrität und Sicherheit zu gewährleisten. Führe regelmäßige Tests durch, um sicherzustellen, dass nur die Daten des richtigen Mandanten angezeigt werden.
Bei schema-basierter Trennung solltest Du individuelle Indexe und Datenbankoptimierungen für jeden Mandanten in Betracht ziehen, um die Performance hoch zu halten.
Multi-Tenancy erweitert die Möglichkeiten Deiner Django-Anwendung erheblich und bietet Flexibilität, Skalierbarkeit und eine saubere Mandanten-Trennung. Mit diesen Techniken kannst Du besser auf unterschiedliche Kundenbedürfnisse eingehen und Deine Anwendung sicher und effizient gestalten.
Finden Sie interessante und zum Thema passende Kurse
Lernen Sie Django in nur 5 Tagen mit diesem umfassenden Intensivkurs! Vom Einstieg in die Entwicklung Ihrer ersten Webanwendung bis hin zu fortgeschrittenen Themen wie API-Entwicklung und Testing – dieser Kurs deckt alles ab. Perfekt für Entwickler, die schnell produktiv mit Django arbeiten möchten.
5 Tage Vollzeit Online
Nächster Termin: 6. Januar 2025
Preis pro Person: 1600,00 EUR
Rabattaktion: 3 für den Preis von 2!
Entdecken Sie die fortgeschrittenen Funktionen von Django in unserem intensiven Aufbaukurs. Dieser Kurs richtet sich an Entwickler, die bereits mit den Grundlagen von Django vertraut sind und ihre Fähigkeiten auf das nächste Level bringen möchten. Lernen Sie, wie Sie komplexe Anwendungen mit Docker erstellen, eine CD/CI-Pipeline anlegen, APIs integrieren und das Projekt auf einen Server deployen.
5 Tage Vollzeit Online
Nächster Termin: 10. März 2025
Preis pro Person: 1900,00 EUR
Rabattaktion: 3 für den Preis von 2!
In diesem intensiven 5-Tage-Seminar lernen Entwickler, professionelle REST-APIs mit dem Django REST Framework zu erstellen, zu optimieren und zu testen.
5 Tage Vollzeit Online
Nächster Termin: 27. Januar 2025
Preis pro Person: 1600,00 EUR
Rabattaktion: 3 für den Preis von 2!