django-tenants added, and configurated customers app
This commit is contained in:
@@ -13,27 +13,32 @@ ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
|
|||||||
|
|
||||||
|
|
||||||
# APPS
|
# APPS
|
||||||
|
SHARED_APPS = [
|
||||||
|
'django_tenants',
|
||||||
|
'core.apps.customers',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
]
|
||||||
|
|
||||||
DJANGO_APPS = [
|
DJANGO_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
]
|
]
|
||||||
|
|
||||||
LOCAL_APPS = [
|
TENANT_APPS = [
|
||||||
|
'core.apps.shared',
|
||||||
]
|
]
|
||||||
|
|
||||||
PACKAGES = [
|
PACKAGES = []
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
INSTALLED_APPS = DJANGO_APPS + PACKAGES + LOCAL_APPS
|
INSTALLED_APPS = SHARED_APPS + DJANGO_APPS + PACKAGES + TENANT_APPS
|
||||||
|
|
||||||
# Middlewares
|
# Middlewares
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
'django_tenants.middleware.main.TenantMainMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@@ -65,7 +70,7 @@ WSGI_APPLICATION = 'config.wsgi.application'
|
|||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.postgresql',
|
'ENGINE': 'django_tenants.postgresql_backend',
|
||||||
'NAME': env.str('POSTGRES_DB'),
|
'NAME': env.str('POSTGRES_DB'),
|
||||||
'USER': env.str('POSTGRES_USER'),
|
'USER': env.str('POSTGRES_USER'),
|
||||||
'PASSWORD': env.str('POSTGRES_PASSWORD'),
|
'PASSWORD': env.str('POSTGRES_PASSWORD'),
|
||||||
@@ -74,6 +79,10 @@ DATABASES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DATABASE_ROUTERS = (
|
||||||
|
'django_tenants.routers.TenantSyncRouter',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
@@ -103,3 +112,8 @@ MEDIA_ROOT = BASE_DIR / 'resources/media'
|
|||||||
|
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
# Django tenants
|
||||||
|
TENANT_MODEL = "customers.Client"
|
||||||
|
|
||||||
|
TENANT_DOMAIN_MODEL = "customers.Domain"
|
||||||
|
|||||||
0
core/apps/customers/__init__.py
Normal file
0
core/apps/customers/__init__.py
Normal file
2
core/apps/customers/admin/__init__.py
Normal file
2
core/apps/customers/admin/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from .domain import *
|
||||||
|
from .client import *
|
||||||
11
core/apps/customers/admin/client.py
Normal file
11
core/apps/customers/admin/client.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from core.apps.customers.models import Client
|
||||||
|
from core.apps.customers.admin.domain import DomainInline
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Client)
|
||||||
|
class ClientAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'name', 'schema_name']
|
||||||
|
search_fields = ['name']
|
||||||
|
inlines = [DomainInline]
|
||||||
8
core/apps/customers/admin/domain.py
Normal file
8
core/apps/customers/admin/domain.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from core.apps.customers.models import Domain
|
||||||
|
|
||||||
|
|
||||||
|
class DomainInline(admin.TabularInline):
|
||||||
|
model = Domain
|
||||||
|
extra = 0
|
||||||
10
core/apps/customers/apps.py
Normal file
10
core/apps/customers/apps.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CustomersConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'core.apps.customers'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import core.apps.customers.admin
|
||||||
|
|
||||||
22
core/apps/customers/management/commands/create_client.py
Normal file
22
core/apps/customers/management/commands/create_client.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from django.core.management import BaseCommand
|
||||||
|
|
||||||
|
from core.apps.customers.models import Client, Domain
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
client_name = input('Mijoz nomini kiriting: ')
|
||||||
|
schema_name = input('Schema nomini kiriting: ').lower()
|
||||||
|
domain = input('Domain kiriting: ').lower()
|
||||||
|
|
||||||
|
client, created = Client.objects.get_or_create(
|
||||||
|
name=client_name,
|
||||||
|
schema_name=schema_name,
|
||||||
|
)
|
||||||
|
Domain.objects.get_or_create(
|
||||||
|
domain=domain,
|
||||||
|
tenant=client,
|
||||||
|
is_primary=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stdout("Mijoz qo'shildi")
|
||||||
|
|
||||||
42
core/apps/customers/migrations/0001_initial.py
Normal file
42
core/apps/customers/migrations/0001_initial.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-11-19 10:53
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django_tenants.postgresql_backend.base
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Client',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(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_at', models.DateField(auto_now_add=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Domain',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(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,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-11-19 10:57
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('customers', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='client',
|
||||||
|
name='on_trial',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='client',
|
||||||
|
name='paid_until',
|
||||||
|
),
|
||||||
|
]
|
||||||
0
core/apps/customers/migrations/__init__.py
Normal file
0
core/apps/customers/migrations/__init__.py
Normal file
2
core/apps/customers/models/__init__.py
Normal file
2
core/apps/customers/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from .client import *
|
||||||
|
from .domain import *
|
||||||
10
core/apps/customers/models/client.py
Normal file
10
core/apps/customers/models/client.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from django_tenants.models import TenantMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Client(TenantMixin):
|
||||||
|
name = models.CharField(max_length=100)
|
||||||
|
created_at = models.DateField(auto_now_add=True)
|
||||||
|
|
||||||
|
auto_create_schema = True
|
||||||
7
core/apps/customers/models/domain.py
Normal file
7
core/apps/customers/models/domain.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from django_tenants.models import DomainMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Domain(DomainMixin):
|
||||||
|
pass
|
||||||
6
core/apps/customers/urls.py
Normal file
6
core/apps/customers/urls.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
|
||||||
|
]
|
||||||
0
core/apps/shared/__init__.py
Normal file
0
core/apps/shared/__init__.py
Normal file
6
core/apps/shared/apps.py
Normal file
6
core/apps/shared/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class SharedConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'core.apps.shared'
|
||||||
0
core/apps/shared/migrations/__init__.py
Normal file
0
core/apps/shared/migrations/__init__.py
Normal file
1
core/apps/shared/models/__init__.py
Normal file
1
core/apps/shared/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .base import *
|
||||||
9
core/apps/shared/models/base.py
Normal file
9
core/apps/shared/models/base.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModel(models.Model):
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
0
core/apps/shared/urls.py
Normal file
0
core/apps/shared/urls.py
Normal file
@@ -1,5 +1,11 @@
|
|||||||
|
asgiref==3.10.0
|
||||||
|
click==8.3.1
|
||||||
Django==5.2
|
Django==5.2
|
||||||
|
django-environ==0.12.0
|
||||||
|
django-tenants==3.9.0
|
||||||
gunicorn==23.0.0
|
gunicorn==23.0.0
|
||||||
|
h11==0.16.0
|
||||||
|
packaging==25.0
|
||||||
|
psycopg2-binary==2.9.11
|
||||||
|
sqlparse==0.5.3
|
||||||
uvicorn==0.38.0
|
uvicorn==0.38.0
|
||||||
django-environ
|
|
||||||
psycopg2-binary
|
|
||||||
Reference in New Issue
Block a user