Vários clientes usando o mesmo sistema em django, qual a melhor forma de realizar isso?

357 views
Skip to first unread message

Fellipe Henrique

unread,
Jan 8, 2015, 10:24:01 AM1/8/15
to django...@googlegroups.com, python...@googlegroups.com
Amigos,

Hoje tenho um sistema que vai atender vários clientes. Por questões burocráticas e legais, cada cliente terá que possuir um database *separado* dos demais.

Atualmente eu estou trabalhando com subdomains, mas eu a todo cliente novo, tenho que incluir o subdomain na mão, esperar a propagação, criar um wsgi.py e um settings.py pra ele, e aí sim, ele terá acesso ao sistema via: cliente.dominio.com.br

Existe algo que possa 'facilitar' isso? principalmente na parte do criar o subdomain e publica-lo...

Quaisquer dicas são bem vindas.


T.·.F.·.A.·.     S+F
Fellipe Henrique P. Soares

e-mail: > echo "lkrrovknFmsgor4ius" | perl -pe \ 's/(.)/chr(ord($1)-2*3)/ge'
Twitter: @fh_bash

Roger Camargo

unread,
Jan 9, 2015, 9:13:15 AM1/9/15
to django...@googlegroups.com, python...@googlegroups.com
Oi Fellipe,

Já fiz algo parecido. Tanto cada cliente tendo sua base independente, como todos clientes acessando a mesma base (filtrando por site).

Sobre a parte de publicar um subdominio, resolvemos apenas criando entradas no NGINX (cada novo site, um novo arquivo configurando o subdominio)
e fazendo um nginx reload.
No mesmo segundo, o novo site (subdominio) esta no ar.

Em outras palavras, o DNS aponta para 1 servidor, e o NGINX gerencia os subdominios.

Espero ter respondido a pergunta. Abraço.


Roger

Kleber Soares

unread,
Jan 13, 2015, 9:26:03 AM1/13/15
to python...@googlegroups.com, django...@googlegroups.com
Bom dia Fellipe, não tive tempo de ler todas as respostas da galera aqui (desculpe se eu repetir algo).

Vou contar a minha experiência.

Tenho um sistema que roda para vários clientes, cada um com seu subdomínio e base de dados.

O domínio foi registrado no godaddy.
O servidor fica no linode e utilizo o gerenciamento de DNS dele mesmo.
As ferramentas que utilizo são: gunicorn + supervisor + ngix + django + python 
A app do django que utilizo para gerenciar os tenants é a: https://github.com/bcarneiro/django-tenant-schemas (do Bernardo, que sempre foi muito solicito quando precisei)

Tentei montar uma forma de não ter muito trabalho na hora de incluir um novo cliente.
Como ficou:
No meu ngix já deixamos configurado *.meudominio.com.br e apartir daí, qualquer subdomínio que for cadastrado no DNS do linode o ngix já reconhece e não temos que esperar nenhum spwan!
No admin do django tenho um cadastro de clientes onde simplesmente cadastro o nome e o subdomínio do cliente, depois criamos uma action onde crio um superusuário para aquele cliente e pronto.

Espero ter sido claro! hahahha...
Mas qualquer dúvida estou a disposição.
Abraço.

Kleber Soares

unread,
Jan 13, 2015, 3:47:55 PM1/13/15
to python...@googlegroups.com, django...@googlegroups.com
Fellipe, no meu caso ficou assim:

Tenho apenas 1 settings.py, utilizo o django-decouple e dj-database-url, assim não tenho que ficar fazendo um settings para cada cliente.

O django-tennant-schemas te dá a possibilidade de escolher as apps que você quer que fiquem compartilhadas ou não, através do settings. 
Nós optamos por deixar um Super User para cada cliente.

settings.py:
ALLOWED_HOSTS = [
    '.myapp.com',
]

SHARED_APPS = (
    'tenant_schemas',  # mandatory
    'customers',  # you must list the app where your tenant model resides in

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # your tenant-specific apps
    'myapp.core',
    ...
)

TENANT_APPS = (
    # The following Django contrib apps must be in TENANT_APPS
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # your tenant-specific apps
    'myapp.core',
    ...
)

INSTALLED_APPS = SHARED_APPS + TENANT_APPS

TENANT_MODEL = "customers.Client"

DATABASES = {
    'default': config(
        'DATABASE_URL',
        default='postgres://postgres:123@localhost/myapp',
        cast=db_url),
}
DATABASES['default']['ENGINE'] = 'tenant_schemas.postgresql_backend'


No Admin.py do app customers criamos a action para criar um Super User padrão a cada clientes adicionado.

admin.py
from django.contrib.auth.models import User
from django.db import connection

from models import Client


def create_admin(self, request, queryset):
    for obj in queryset:
        # define qual o schema será utilizado para criar o super user
        connection.set_schema(obj.schema_name, include_public=False)
        user = User.objects.create_user('superusername', 'superuseremail', 'superuserpassword')
        user.is_staff = True
        user.is_active = True
        user.is_superuser = True
        user.save()
        >>>> aqui você pode preencher outros models da forma que quiser.
        # retorna o schema público
        connection.set_schema_to_public()
create_admin.short_description = "Criar administrador"


class ClientAdmin(admin.ModelAdmin):
    ...
    actions = [create_admin]


admin.site.register(Client, ClientAdmin)

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)

    # default true, schema will be automatically created
    # and synced when it is saved
    auto_create_schema = True

    def __unicode__(self):
        return unicode(self.name)

    class Meta:
        verbose_name = u'Cliente'
        verbose_name_plural = u'Clientes'

 
Com isso conseguimos resolver esses dois itens que vc mencionou:
  1. Acesso ao admin (pois criando um super user vc terá acesso na hora.)
  2. Criar super user e popular outros models

Precisando, estamos por aqui.



Em quinta-feira, 8 de janeiro de 2015 12:24:03 UTC-3, Fellipe Henrique escreveu:

Kleber Soares

unread,
Jan 14, 2015, 8:47:08 AM1/14/15
to python...@googlegroups.com, django...@googlegroups.com
Fellipe, vc tentou: 
python manage.py sync_schemas



Em quinta-feira, 8 de janeiro de 2015 12:24:03 UTC-3, Fellipe Henrique escreveu:

Kleber Soares

unread,
Jan 14, 2015, 8:49:21 AM1/14/15
to python...@googlegroups.com, django...@googlegroups.com
Criou o tenant public também?

from customers.models import Client

# create your public tenant
tenant = Client(domain_url='my-domain.com', # don't add your port or www here! on a local server you'll want to use localhost here
               
schema_name='public',
               
name='Schemas Inc.',
               
paid_until='2016-12-05',
               
on_trial=False)
tenant.save()



Em quinta-feira, 8 de janeiro de 2015 12:24:03 UTC-3, Fellipe Henrique escreveu:

Kleber Soares

unread,
Jan 16, 2015, 7:22:02 PM1/16/15
to python...@googlegroups.com, django...@googlegroups.com
Desculpa não ter ajudado mais Fellipe, acabei sem tempo de ver os emails. =\
Mas estou feliz que você tenha conseguido! :D
Quando precisei fazer esse esquema de multi-tenant também passei por mals bocados hahahah... 
Como o amigo Fabio falou, é um assunto que interessa há várias pessoas no grupo e poucos tem conhecimento no assunto! 
Até tem um conteúdo gringo, mas muito particionado e antigo.





Em quinta-feira, 8 de janeiro de 2015 12:24:03 UTC-3, Fellipe Henrique escreveu:
Reply all
Reply to author
Forward
0 new messages