From 9599e25e2d9607f4f4203f18c5535bbbe2b26623 Mon Sep 17 00:00:00 2001 From: Jonas Legion Date: Thu, 10 Jun 2021 12:59:22 +0200 Subject: [PATCH] install django tenant --- DjangoFiles/Administration/__init__.py | 0 DjangoFiles/Administration/admin.py | 8 ++++ DjangoFiles/Administration/apps.py | 5 ++ .../Administration/migrations/__init__.py | 0 DjangoFiles/Administration/models.py | 3 ++ DjangoFiles/Administration/tests.py | 3 ++ DjangoFiles/Administration/views.py | 3 ++ DjangoFiles/Customers/__init__.py | 0 DjangoFiles/Customers/admin.py | 3 ++ DjangoFiles/Customers/apps.py | 5 ++ .../Customers/migrations/0001_initial.py | 42 +++++++++++++++++ .../migrations/0002_create_tenant_public.py | 46 +++++++++++++++++++ DjangoFiles/Customers/migrations/__init__.py | 0 DjangoFiles/Customers/models.py | 14 ++++++ DjangoFiles/Customers/tests.py | 3 ++ DjangoFiles/Customers/views.py | 3 ++ DjangoFiles/TiBillet/settings.py | 38 +++++++++++---- Docker/bashrc | 2 + 18 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 DjangoFiles/Administration/__init__.py create mode 100644 DjangoFiles/Administration/admin.py create mode 100644 DjangoFiles/Administration/apps.py create mode 100644 DjangoFiles/Administration/migrations/__init__.py create mode 100644 DjangoFiles/Administration/models.py create mode 100644 DjangoFiles/Administration/tests.py create mode 100644 DjangoFiles/Administration/views.py create mode 100644 DjangoFiles/Customers/__init__.py create mode 100644 DjangoFiles/Customers/admin.py create mode 100644 DjangoFiles/Customers/apps.py create mode 100644 DjangoFiles/Customers/migrations/0001_initial.py create mode 100644 DjangoFiles/Customers/migrations/0002_create_tenant_public.py create mode 100644 DjangoFiles/Customers/migrations/__init__.py create mode 100644 DjangoFiles/Customers/models.py create mode 100644 DjangoFiles/Customers/tests.py create mode 100644 DjangoFiles/Customers/views.py diff --git a/DjangoFiles/Administration/__init__.py b/DjangoFiles/Administration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/Administration/admin.py b/DjangoFiles/Administration/admin.py new file mode 100644 index 0000000..60b2a4f --- /dev/null +++ b/DjangoFiles/Administration/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django_tenants.admin import TenantAdminMixin + +from Customers.models import Client + +@admin.register(Client) +class ClientAdmin(TenantAdminMixin, admin.ModelAdmin): + list_display = ('name', 'paid_until') \ No newline at end of file diff --git a/DjangoFiles/Administration/apps.py b/DjangoFiles/Administration/apps.py new file mode 100644 index 0000000..bad86a2 --- /dev/null +++ b/DjangoFiles/Administration/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AdministrationConfig(AppConfig): + name = 'Administration' diff --git a/DjangoFiles/Administration/migrations/__init__.py b/DjangoFiles/Administration/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/Administration/models.py b/DjangoFiles/Administration/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/DjangoFiles/Administration/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/DjangoFiles/Administration/tests.py b/DjangoFiles/Administration/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/DjangoFiles/Administration/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/DjangoFiles/Administration/views.py b/DjangoFiles/Administration/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/DjangoFiles/Administration/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/DjangoFiles/Customers/__init__.py b/DjangoFiles/Customers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/Customers/admin.py b/DjangoFiles/Customers/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/DjangoFiles/Customers/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/DjangoFiles/Customers/apps.py b/DjangoFiles/Customers/apps.py new file mode 100644 index 0000000..224f9ad --- /dev/null +++ b/DjangoFiles/Customers/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CustomersConfig(AppConfig): + name = 'Customers' diff --git a/DjangoFiles/Customers/migrations/0001_initial.py b/DjangoFiles/Customers/migrations/0001_initial.py new file mode 100644 index 0000000..7e05e9d --- /dev/null +++ b/DjangoFiles/Customers/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# Generated by Django 3.1 on 2021-06-10 10:54 + +from django.db import migrations, models +import django.db.models.deletion +import django_tenants.postgresql_backend.base + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Client', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('schema_name', models.CharField(db_index=True, max_length=63, unique=True, validators=[django_tenants.postgresql_backend.base._check_schema_name])), + ('name', models.CharField(max_length=100)), + ('paid_until', models.DateField()), + ('on_trial', models.BooleanField()), + ('created_on', models.DateField(auto_now_add=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Domain', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('domain', models.CharField(db_index=True, max_length=253, unique=True)), + ('is_primary', models.BooleanField(db_index=True, default=True)), + ('tenant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domains', to='Customers.client')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/DjangoFiles/Customers/migrations/0002_create_tenant_public.py b/DjangoFiles/Customers/migrations/0002_create_tenant_public.py new file mode 100644 index 0000000..b05b4e5 --- /dev/null +++ b/DjangoFiles/Customers/migrations/0002_create_tenant_public.py @@ -0,0 +1,46 @@ +# Generated by Django 3.1 on 2021-06-10 10:56 +import os +from django.db import migrations + + +def create_premier_tenant(apps, schema_editor): + # We can't import the Person model directly as it may be a newer + # version than this migration expects. We use the historical version. + Client = apps.get_model('Customers', 'Client') + Domain = apps.get_model('Customers', 'Domain') + DNS = os.getenv('DOMAIN') + + tenant_public = Client.objects.get_or_create(schema_name='public', + name='Tibillet Public', + paid_until='2200-12-05', + on_trial=False)[0] + + # Add one or more domains for the tenant + domaine_seul = Domain.objects.get_or_create(domain=DNS, + tenant=tenant_public, + is_primary=True, + ) + + domaine_www = Domain.objects.get_or_create(domain=f'www.{DNS}', + tenant=tenant_public, + is_primary=False, + ) + + return tenant_public, domaine_seul[0], domaine_www[0] + + +def reverse(apps, schema_editor): + tenant_public, domaine_seul, domaine_www = create_premier_tenant(apps, schema_editor) + tenant_public.delete() + domaine_seul.delete() + domaine_www.delete() + + +class Migration(migrations.Migration): + dependencies = [ + ('Customers', '0001_initial'), + ] + + operations = [ + migrations.RunPython(create_premier_tenant, reverse), + ] diff --git a/DjangoFiles/Customers/migrations/__init__.py b/DjangoFiles/Customers/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/DjangoFiles/Customers/models.py b/DjangoFiles/Customers/models.py new file mode 100644 index 0000000..86b9b2c --- /dev/null +++ b/DjangoFiles/Customers/models.py @@ -0,0 +1,14 @@ +from django.db import models +from django_tenants.models import TenantMixin, DomainMixin + +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) + + # default true, schema will be automatically created and synced when it is saved + auto_create_schema = True + +class Domain(DomainMixin): + pass diff --git a/DjangoFiles/Customers/tests.py b/DjangoFiles/Customers/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/DjangoFiles/Customers/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/DjangoFiles/Customers/views.py b/DjangoFiles/Customers/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/DjangoFiles/Customers/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/DjangoFiles/TiBillet/settings.py b/DjangoFiles/TiBillet/settings.py index 2e7f574..184d187 100644 --- a/DjangoFiles/TiBillet/settings.py +++ b/DjangoFiles/TiBillet/settings.py @@ -15,7 +15,6 @@ from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve(strict=True).parent.parent - # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ @@ -31,19 +30,38 @@ else: ALLOWED_HOSTS = ['*'] - # Application definition -INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', +SHARED_APPS = ( + 'django_tenants', # mandatory + 'Customers', # you must list the app where your tenant model resides in + 'django.contrib.contenttypes', + + # everything below here is optional + 'django.contrib.auth', 'django.contrib.sessions', + 'django.contrib.sites', 'django.contrib.messages', - 'django.contrib.staticfiles', -] + 'django.contrib.admin', + + 'Administration', +) + +TENANT_APPS = ( + # The following Django contrib apps must be in TENANT_APPS + 'django.contrib.contenttypes', + + # your tenant-specific apps +) + +INSTALLED_APPS = list(SHARED_APPS) + [app for app in TENANT_APPS if app not in SHARED_APPS] +TENANT_MODEL = "Customers.Client" # app.Model +TENANT_DOMAIN_MODEL = "Customers.Domain" # app.Model + MIDDLEWARE = [ + 'django_tenants.middleware.main.TenantMainMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -73,7 +91,6 @@ TEMPLATES = [ WSGI_APPLICATION = 'TiBillet.wsgi.application' - # Database # https://docs.djangoproject.com/en/3.1/ref/settings/#databases @@ -88,6 +105,9 @@ DATABASES = { } } +DATABASE_ROUTERS = ( + 'django_tenants.routers.TenantSyncRouter', +) # Password validation # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators @@ -107,7 +127,6 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] - # Internationalization # https://docs.djangoproject.com/en/3.1/topics/i18n/ @@ -121,7 +140,6 @@ USE_L10N = True USE_TZ = True - # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ diff --git a/Docker/bashrc b/Docker/bashrc index a5bcaad..a8fb3f5 100644 --- a/Docker/bashrc +++ b/Docker/bashrc @@ -1,6 +1,8 @@ # only for convenient :) alias mm="python /DjangoFiles/manage.py migrate" +# alias mm="python /DjangoFiles/manage.py migrate_schemas --shared" + alias sp="python manage.py tenant_command shell_plus" alias rsp="python /DjangoFiles/manage.py runserver_plus 0.0.0.0:8002" alias flush="python manage.py flushall --noinput"