Aplicação multi-tenant (uma base ou schema por cliente)

367 views
Skip to first unread message

Matheus Lima

unread,
Aug 13, 2013, 12:36:04 AM8/13/13
to django...@googlegroups.com
Alguém já conseguiu criar um projeto multi-tenant (um banco ou schema pra cada cliente) com Django?

Basicamente é uma aplicação SaaS, mas por motivo de segurança e garantir a integridade, queria ter uma base ou um schema por cliente.

Minha principal dúvida é relação as migrações de banco de dados com South. Como eu faria pra executar as migrations em cada base?

Alguém já conseguiu criar uma aplicação desse tipo?

--
Att,

Matheus dos Santos Lima     

Matheus Lima

unread,
Aug 13, 2013, 12:42:49 AM8/13/13
to django...@googlegroups.com
Um detalhe é que não quero ter que adicionar não a configuração na setting "DATABASE".

A solução que prevejo é um middleware pra modifiar o schema de acordo com o usuário que fez a requisição. E no model de usuário ter um campo pra dizer qual é seu schema.

Guilherme David da Costa

unread,
Aug 13, 2013, 3:31:04 AM8/13/13
to django...@googlegroups.com
A última vez que fiz isso não havia nenhuma lib que facilita-se então foi via middleware mesmo.
Hoje em dia não sei mais como as coisas estão.


2013/8/13 Matheus Lima <mathe...@gmail.com>

--
Você está recebendo esta mensagem porque se inscreveu no grupo "Django Brasil" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para django-brasi...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.
 
 



--
my e-mail composition:
80% -> garbage
9%   -> serious
11% -> me doesn't making any sense

Welkson Renny de Medeiros

unread,
Aug 13, 2013, 7:30:43 AM8/13/13
to django...@googlegroups.com

Gleison Rodrigues

unread,
Aug 13, 2013, 8:10:17 AM8/13/13
to django...@googlegroups.com
@Matheus Lima a solução apresentada resolveu o seu problema?

--
Poder é sabedoria.
""""""""""""""""""""""""
Gleison Rodrigues
Desenvolvedor WEB
""""""""""""""""""""""""


Mauro Risonho de Paula Assumpção

unread,
Aug 13, 2013, 8:50:32 AM8/13/13
to django...@googlegroups.com

Arthur Furlan

unread,
Aug 13, 2013, 8:50:28 AM8/13/13
to django...@googlegroups.com
Meus 2 centavos: aumentar o número de databases *não* garante maior
segurança ou integridade(?), só vai fazer com que você tenha que:
aplicar migrations em N bancos ao invés de um só, se preocupar com a
performance de N bancos ao invés de 1 só, e em caso de desastre, tenha
que recuperar N databases corrompidos ao invés de 1 só ou subir N
backups ao invés de um só.


-- Arthur Furlan


2013/8/13 Gleison Rodrigues <xgle...@gmail.com>:

Gleison Rodrigues

unread,
Aug 13, 2013, 9:07:36 AM8/13/13
to django...@googlegroups.com
Boas observações @Arthur Furlan e muito pertinentes.
Vc tem alguma dica de como contonar esse problema do @Matheus Lima?

Arthur Furlan

unread,
Aug 13, 2013, 9:22:34 AM8/13/13
to django...@googlegroups.com
Para rodar as migrations em todos os bancos, eu criaria um management
command que fizesse isso automaticamente:


class Command(BaseCommand):

def handle(self):
DATABASES = ['database1', 'database2', 'database3']
for database in DATABASES:
call_command('migrate', ['--database=' + database])


E depois chamaria "global_migratie" ao invés de "migrate":

$ python manage.py global_migrate

Roger Camargo

unread,
Aug 13, 2013, 9:30:57 AM8/13/13
to django...@googlegroups.com

Oi Matheus,

Estou trabalhando em um projeto multi-tenant usando django.
Acredito que existem outras formas, mas a solução que era para ser temporária,
ficou definitiva e vem funcionando bem a pelo menos 2 anos:

Em resumo, 1 base para CADA cliente. E um script que usa o south para fazer migration 

Detalhes:

1 - Existem diversas apps com o core do negório:
(seguindo a ideia de pluggable apps)
app-core1
app-core2
app-core3
app-core4
...

2 - Para cada novo cliente, é criado um novo projeto (quase vazio) contendo
em INSTALLED_APPS as apps-core.

3 - No deploy, existe um script que faz um loop sobre todos os projetos rodando migrate --all (south),
o qual atualiza a base de dados para cada cliente.


Já vi em projetos não django, cada tabela conter um campo id_empresa (para ter apenas 1 base de dados).

Enfim, este assunto me interessa, se alguem tiver mais informações ou exemplos para compartilhar

Abraço,

Roger

Fellipe Henrique

unread,
Aug 13, 2013, 9:38:58 AM8/13/13
to django...@googlegroups.com
Fiz algo parecido, mas pra mim eu tive que alterar o settings, porque cada user tinha que conectar em um banco diferente, dê uma lida aqui [1], talvez você consiga modificar algo pra seu uso.

[]s




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

Twitter: @fh_bash


Arthur Furlan

unread,
Aug 13, 2013, 9:41:07 AM8/13/13
to django...@googlegroups.com
Eu tenho um SaaS também e já tive outros também. Todos os clientes usam o mesmo banco de dados, isso minimiza a manutenção do sistema, agiliza o deploy da aplicação e facilita os processos internos da empresa (como não ter criar nada manualmente sempre que um novo cliente entra).

Funciona parecido como você falou mesmo, nas tabela que precisam de relacionamento existe um campo "cliente" mas isso não acontece em todas as tabelas, não é necessário.





-- Arthur Furlan


2013/8/13 Roger Camargo <huog...@gmail.com>

Fellipe Henrique

unread,
Aug 13, 2013, 9:43:40 AM8/13/13
to django...@googlegroups.com

Em 13 de agosto de 2013 10:41, Arthur Furlan <afu...@afurlan.org> escreveu:
nas tabela que precisam de relacionamento existe um campo "cliente" mas isso não acontece em todas as tabelas, não é necessário

Arthur, andei lendo e vi que o django ainda tem problemas quando o model possui mais de um field como PK, isso ainda é verdade? Se for, como você faz com os FK?

Arthur Furlan

unread,
Aug 13, 2013, 10:13:28 AM8/13/13
to django...@googlegroups.com
2013/8/13 Fellipe Henrique <fell...@gmail.com>:
>
> Em 13 de agosto de 2013 10:41, Arthur Furlan <afu...@afurlan.org> escreveu:
>
>> nas tabela que precisam de relacionamento existe um campo "cliente" mas
>> isso não acontece em todas as tabelas, não é necessário
>
>
> Arthur, andei lendo e vi que o django ainda tem problemas quando o model
> possui mais de um field como PK, isso ainda é verdade? Se for, como você faz
> com os FK?

Eu não uso chaves compostas, sempre utilizo o campo "id" do Django.

Para as restrições de unicidade eu uso o "unique_together" e quando
preciso realmente garantir algum comportamento que o "unique_together"
não suporta, adiciono a constraint no diretório "sql" e depois rodo
manualmente no banco de dados... mas isso só aconteceu 1 vez até hoje
e foi um caso bastante específico.


-- Arthur Furlan

Fabio C. Barrionuevo da Luz

unread,
Aug 13, 2013, 10:20:58 AM8/13/13
to django...@googlegroups.com
Aqui tem uma discussão sobre múltiplos schemas[1] e aqui uma possivel solução[2].

Não sei se ajuda para o caso especifico deste tópico.

[1] https://code.djangoproject.com/ticket/6148#comment:147
[2] https://github.com/cbmi/django/commit/4dccd11d927898523e4edfa0379b8b0530cd987f




--
Você está recebendo esta mensagem porque se inscreveu no grupo "Django Brasil" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para django-brasi...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.



--
Fábio C. Barrionuevo da Luz
Acadêmico de Sistemas de Informação na Faculdade Católica do Tocantins - FACTO
Palmas - Tocantins - Brasil - América do Sul

Kleber Soares

unread,
Aug 14, 2013, 10:29:56 PM8/14/13
to django...@googlegroups.com
Alguns meses atras iniciei um projeto para orgãos públicos e senti a nescessidade de usar multi-tenant também, pois em meu caso específico não seria justo uma prefeitura de interior (por exemplo) com poucas movimentações, ter uma base grande como a de uma capital, buscas que deveriam ser rápidas se tornariam mais lentas e como a internet nesses interiores é mais lenta, quanto mais leve melhor.

Utilizei o projeto: https://github.com/bcarneiro/django-tenant-schemas/blob/master/README.markdown

Kleber Soares

unread,
Aug 14, 2013, 10:30:34 PM8/14/13
to django...@googlegroups.com

Cristiano Cortezia

unread,
Aug 15, 2013, 10:40:24 AM8/15/13
to django...@googlegroups.com
Em dois projetos distintos, apliquei duas das técnicas mencionadas aqui: (1) uma base port tenant, e (2) uma base única usando tenant_id.

Em (1)
 - criei um middleware para descobrir o tenant a partir de detalhes da requisição e injetar a informação no objeto request.
 - utilizo um database router para descobrir qual banco usar a partir da informação injetada.
 - fui obrigado a usar uma variável global (thread local) para suportar os routers. (Sugestões são bem vindas).
 - altero os settings on-the-fly para permitir a criação de novos tenants via web, e não precisar alterar o settings.py. (Reconheço os perigos).
Resultado
  - aumentou bastante a complexidade.
  - eliminou todos os bugs de acesso cross-tenant.
  - apaguei bastante código de teste que validava cross-tenant.
  - melhorou a performance.

Em (2)
  - apliquei a solução simples de inserir o campo no modelo.
Resultado
  - simples.
  - necessário tratar as questões de unique_together.
  - necessário testar código contra bugs de cross-tenant.


Se alguém quiser trocar idéia, me passa um email.

Abs
Reply all
Reply to author
Forward
0 new messages