Na verdade esse tipo de modelagem é bem 'cabeluda' mesmo... Existem modelos
extremamente complexos para tratar dessa relação PF, PJ, Contato e Endereço
e, muitas vezes, o que a gente faz são 'otimizações' para simplificar o
modelo. O problema é que essas tais otimizações são feitas em cima de restrições
que impomos ao modelo.
2010/6/22 Pablo Lorenzon <pabl...@gmail.com>:
> Pessoal, estou com uma dúvida na minha implementação, com relação a parte
> conceitual de como tratar algumas coisas no Django, ai vai:
>
> tenho as seguintes classes:
[corta codigo]
> O correto seria que ao cadastrar um Cliente (PF ou PJ) e, cada um possuir
> seu(s) contato(s) e suas cidade(s), tendo em vista que um cliente pode ter
> varios contatos e ou cidades. Quando cadastro um contato para um cliente, o
> mesmo cadastro fica disponivel na lista de contatos, quando vou cadastrar um
> novo usuário o sistema traz o contato já existente para o outro cliente.
> Qual a maneira correta de fazer as ligações para que os vinculos de contatos
> e cidades por exemplo, sejam atribuidos para o cliente em questão e não
> listados para todos?
Eu vou listar +/- um modelo que costumava usar antigamente mas já digo logo que
ele apresenta algumas 'limitações' impostas...
Vale observar que eu uso herança de Models e algumas regrinhas devem ser
observadas quando usamos herança com o ORM do Django.
# Pessoas
class Pessoa(Model):
# Crio essa classe para definir uma interface comum
# para pessoas.
contatos = ManyToMany(Contato)
:
class PJ(Pessoa): ...
razao_social = CharField()
cnpj = CharField()
:
class PF(Pessoa): ...
nome = CharField()
cpf = CharField()
:
# Contato
class Contato(Model):
pass
class Endereco(Contato): ...
logradouro = FK(Logradouro)
numero = CharField()
complemento = CharField()
class Telefone(Contato): ...
numero = CharField()
class ContatoPessoa(Contato): ...
pessoa = FK(Pessoa)
class EMail(Contato): ...
email = EMailField()
# Endereço
class Logradouro(Model):
cep = CharField()
logradouro = CharField() # Rua ...
bairro = CharField()
cidade = FK(Cidade)
class Cidade(Model):
nome = CharField()
estado = FK(Estado) # se o seu software precisar rodar fora do .br
# senão é só usar um Choice aqui...
Esse modelo tem complexidade média mas é muito flexível. Você pode
'cortar' algumas
coisas dele para simplificar ou adicionar coisas extras para atender às suas
necessidades.
Valeu,
Osvaldo
--
Curso de Desenvolvimento Web com Python e Django — R$200,00 (12xR$19,00)
http://www.ludeos.com.br/s/triveos-cursos-online
--
Osvaldo Santana Neto -- Triveos Tecnologia
Cel.: +55 41 9244 1646
--
Django Brasil em Google Groups <http://groups.google.com.br/group/django-brasil>
Associe-se à Python Brasil e suporte nossa comunidade! <http://associacao.python.org.br/>
2010/6/22 Pablo Lorenzon <pabl...@gmail.com>:
> OK, compreendi, mas me diz uma coisa, neste modelo exemplo que você me
> passou:
>
> class ContatoPessoa(Contato): ...
> pessoa = FK(Pessoa)
>
>
> só esta realizando os contatos para Pessoa fisica, para Juridica teria que
> colocar outra FK, ficaria:
>
> class ContatoPessoa(Contato):
> pf = FK(Pessoa)
> pj = FK(pessoa)
Não... você pode aproveitar a classe Pessoa 'comum' aos dois tipos:
class ContatoPessoa(Contato:
pessoa = FK(Pessoa)
Aí, neste caso, não importa qual o tipo de pessoa a ser contactada. Você usaria
a propriedade polimórfica (oh! palavra chique :D)...
Eu costumo ter um atributo "contato_principal" nas classes PessoasJuridicas para
fazer a delegação dos métodos 'comuns' de contato... ex:
class PF(Pessoa):
def envia_email(self, ...):
email = self.contatos.filter(tipo="email") # ou algo assim..
send(email, ...)
class PJ(Pessoa):
def envia_email(self, ...):
try:
self.contato_principal.envia_email(...)
except AttributeError: # contato principal não tem e-mail
# trata da melhor maneira...
# tente achar algum contato que tenha e-mail
# ou retorne uma mensagem de erro para o usuário
# ou 'finja que nada aconteceu' :D (brincadeira)
As regras de negócio, neste caso, vão ter que ser definidas por sua conta...
O que a modelagem te oferece é só um mecanismo para que você possa incluí-las
tranquilamente.
> e mesmo assim os contatos de um objeto PF não ficariam sendo listados quando
> for realizado um novo cadastro de PF?
Não entendi a pergunta...
2010/6/23 Pablo Lorenzon <pabl...@gmail.com>:
> Vou explicar melhor, espero que possa me ajudar, por exemplo, eu tenho a
> classe Pessoa() como abstrata, esta classe instancia atributos comuns entre
> as classes PessoaFisica(Pessoa) e PessoaJuridica(Pessoa). Em um outro model
> (aplicação) que se refere a uma funcionalidade para registrar cotação eu
> gostaria de ter um campo onde vou digitar o nome da Pessoa (cliente
> cadastrado , seja este PF ou PJ) ,e o sistema vai buscar tanto as PFs quanto
> as PJs existentes, trazendo com autocomplete algo parecido os clientes
> (Pessoas) existentes para que eu selecione o que eu preciso para realizar a
> cotação, compreende? Tem como fazer isso? Não estou encontrando uma forma de
> realizar esta composição para o campo.
Entendi o problema.
Depende de como você modelou essa derivação (herança) no ORM do Django (e
consequentemente no seu banco de dados).
http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance
Mas no caso mais comum você faria simplesmente:
Pessoa.objects.filter(nome=...)
E esse queryset retornaria resultados de todos os tipos de Pessoa com nome
igual a "...".
Nos casos mais complicados as coisas ficariam um pouco mais...
digamos... complicadas :D