Ligações entre models, chaves FK E PK

268 views
Skip to first unread message

Pablo Lorenzon

unread,
Jun 15, 2010, 9:21:49 AM6/15/10
to django...@googlegroups.com
Bom dia a todos,

Venho através deste email solicitar um auxilio para o desenvolvimento de uma aplcação em django que estou realizando. A minha estrutura e duvidas são as seguintes:

possuo uma app chamada cadastro, nesta app faço o cadastro de Pessoas Físicas e Jurídicas, sendo que o model está implementado da seguinte forma:

class Pessoa(models.Model):
       dados comuns entre pessoa física e juridica...
      
       class Meta:
             abstract = True



class PessoaFisica(Pessoa):
   cpf = ...
   rg = ...


class PessoaJuridica(Pessoa):
   cnpj = ...
   inscr_estadual = ...


Em uma segunda app chamada cotacoes, tenho o model:

class RegistraCotacoes(models.Model):
   atribustos para registrar cotacoes....



* O que eu quero fazer é o seguinte, preciso que na classe RegistraCotacoes possam ser listadas tanto Pessoas Fisicas quanto Juridicas, para o usuário esta seleção deve ser transparente pois, quando necessitar registrar uma cotação é indiferente para ele na hora de pesquisar o cliente se é PF ou PJ, a listagem de nomes deve ser completa, como eu chamo esta associação?

estava bolando um esquema para fazer uma classe da seguinte forma:

class PessoaCotacao(models.Model)
    id_pf = models.ForeygnKey(PessoaFisica)
    id_pj = models.ForeygnKey(PessoaJuridica)
    id = models.Primary_key(id_pf, id_pj)


A idéia é fazer uma chave primária trazendo as ids de PF e PJ, estou no caminho certo? Alguem pode me ajudar a modelar esta estrutura para que atenda a minha necessidade? Qual a melhor implementação para separar cadastros PF e PJ no Django e depois poder utiliza-los de forma unificada para cadastros de outras funções?


Aguardo retorno.
Desde já agradeço a atenção de todos.
 



marcos thomaz

unread,
Jun 15, 2010, 11:51:54 AM6/15/10
to django...@googlegroups.com
Talvez daria pra usar algo baseado em contenttypes[1]
 
[]'s

Marcos Thomaz




De: Pablo Lorenzon <pabl...@gmail.com>
Para: django...@googlegroups.com
Enviadas: Terça-feira, 15 de Junho de 2010 10:21:49
Assunto: Ligações entre models, chaves FK E PK
--
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/>

 

Pablo Lorenzon

unread,
Jun 15, 2010, 12:46:31 PM6/15/10
to django...@googlegroups.com
Dei uma olhada na API mas não consegui compreender direito, você já utilizou contenttypes?

Teria alguma outra alterantiva?

marcos thomaz

unread,
Jun 15, 2010, 8:21:09 PM6/15/10
to django...@googlegroups.com
> Dei uma olhada na API mas não consegui compreender direito, você já utilizou contenttypes?
Usei apenas em testes. De uma forma geral (pelo que entendi e me corrijam por favor se eu estiver errado) ele cria um tipo de relacionamento para qualquer modelo de seu projeto.
Ficaria algo assim [1]
No caso, pastaria você pegar uma instância, tanto de PessoaFisica, quanto de PessoaJuridica e passar para o modelo RegistraCotacoes. Um pequeno exemplo disso está em [2]

>Teria alguma outra alterantiva?
Poderia criar da forma como você havia sugerido, ou seja, com duas chaves.
 
[]'s

Marcos Thomaz


 

Pablo Lorenzon

unread,
Jun 18, 2010, 11:17:31 AM6/18/10
to django...@googlegroups.com
Certo, só tem alguns pontos que ainda tenho duvidas, segue o código abaixo da real necessidade:

Model Cadastro

from django.db import models
from django.contrib.admin.models import User
from django.contrib.localflavor.br.br_states import STATE_CHOICES
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

ESTADO_CIVIL = (
    ('C','Casado(a)'),('S','Solteiro(a)'),('V', 'Viuvo(a)')
    )

TIPO_SEXO = (
    ('F','Feminino'),('M','Masculino')
    )

TIPO_PAG = (
   ('A Vista', 'A Vista'),('30', '30'),('30/60' , '30/60'),('30/60/90' , '30/60/90'),('30/60/90/120' , '30/60/90/120')
   )

SEL_PAIS = (
            (1, 'Brasil'), (2, 'Argentina')
            )

class Cidades(models.Model):
    cidade = models.CharField("Cidade", max_length=200)
    cod_cidade = models.CharField("Codigo da Cidade", max_length=100)
    estado = models.CharField(choices=STATE_CHOICES, max_length=2, verbose_name = 'Estado')
    pais = models.CharField(choices=SEL_PAIS, max_length=2, verbose_name = 'Pais')
   
    #Campo para permitir o relacionamento dinamico com outros modelos cadastrados no sistema
    content_type = models.ForeignKey(ContentType)
    #Este atributo ira armazenar o valor da chave primaria do objeto vinculado. Caso o seu objeto
    #nao tenha como primary key um campo do tipo inteiro, e necessario alterar este campo.
    object_id = models.PositiveIntegerField()
    #Este campo ira guardar o id do objeto na qual o telefone esta vinculado.
    content_object = generic.GenericForeignKey()

   
    def __unicode__(self):
        return self.cidade
   
    class Meta:
        ordering = ['cidade', 'cod_cidade' ]
        db_table = 'cidades'

class Contatos(models.Model):
    nome = models.CharField(max_length=200)
    telefone = models.CharField("Telefone", max_length=12)
    celular = models.CharField("Celular", max_length=12)
    email = models.EmailField("Email", max_length=75)
    setor = models.CharField("Setor da empresa ao qual faz parte", max_length=100)
    funcao = models.CharField("Funcao", max_length=100)
    tmp_empresa = models.CharField("Ha quanto tempo trabalha na empresa", max_length=50)
   
    #Campo para permitir o relacionamento dinamico com outros modelos cadastrados no sistema
    content_type = models.ForeignKey(ContentType)
    #Este atributo ira armazenar o valor da chave primaria do objeto vinculado. Caso o seu objeto
    #nao tenha como primary key um campo do tipo inteiro, e necessario alterar este campo.
    object_id = models.PositiveIntegerField()
    #Este campo ira guardar o id do objeto na qual o telefone esta vinculado.
    content_object = generic.GenericForeignKey()

   
    def __unicode__(self):
        return self.nome
   
    class Meta:
        ordering = ['nome', 'email' ]
        db_table = 'contatos'
       
class FormaPagamento(models.Model):
    frm_pag = models.CharField(choices=TIPO_PAG, max_length=30, verbose_name = 'Forma de Pagamento Padrao')
   
    #Campo para permitir o relacionamento dinamico com outros modelos cadastrados no sistema
    content_type = models.ForeignKey(ContentType)
    #Este atributo ira armazenar o valor da chave primaria do objeto vinculado. Caso o seu objeto
    #nao tenha como primary key um campo do tipo inteiro, e necessario alterar este campo.
    object_id = models.PositiveIntegerField()
    #Este campo ira guardar o id do objeto na qual o telefone esta vinculado.
   
    def __unicode__(self):
        return self.frm_pag
   
    class Meta:
        ordering = ['frm_pag']
       
class Pessoa(models.Model):
    endereco = models.CharField(max_length=200, verbose_name = 'Endereco', blank=False, null=True)
    num = models.CharField(max_length=20, verbose_name = 'Numero', blank=False, null=True)
    complemento = models.CharField("Complemento", max_length=200, null=True, blank=True)
    bairro = models.CharField("Bairro", max_length=200, blank=False, null=True)
    cep = models.PositiveIntegerField('CEP',max_length=9, blank=False, null=True)
    cidade = generic.GenericRelation(Cidades)
    telefone = models.CharField("Telefone", max_length=12)
    fax =  models.CharField("Fax", max_length=12)
    ultimo_cont = models.DateTimeField(verbose_name = 'Ultimo Contato', auto_now_add=True)
    desc_ultimo_cont = models.TextField("Descricao do Ultimo Contato", max_length=255, blank=True, null=True)
    ult_comp_rlz = models.CharField(max_length=200, verbose_name = 'Ultima Compra', blank=True, null=True)
    email = models.EmailField("Email", max_length=75)
    email_fiscal = models.EmailField("Email Fiscal", max_length=75)
    frm_pag = generic.GenericRelation(FormaPagamento)
    datacadastro = models.DateTimeField(auto_now_add=True)

   
    def __unicode__(self):
        return self.id

   
    class Meta:
        abstract = True
        ordering = ['id']
        db_table = 'pessoa'
   
class PessoaFisica(Pessoa):
    nome = models.CharField(max_length=200)
    sobrenome = models.CharField(max_length=200)
    rg = models.CharField(max_length=200, verbose_name='RG', blank=True, null=True)
    cpf = models.CharField(max_length=200, verbose_name='CPF', blank=True, null=True)
    sexo = models.CharField(max_length=1, choices=TIPO_SEXO,  blank=True, null=True)
    data_nascimento = models.DateField(verbose_name='Data de Nascimento', null=True)
    estado_civil = models.CharField(choices=ESTADO_CIVIL, max_length=40, verbose_name = 'Estado Civil')
    msn = models.EmailField("Contato MSN", max_length=75)
    skype = models.CharField("Contato Skype", max_length=75)
    celular = models.CharField("Celular", max_length=12)
   
    def __unicode__(self):
        return self.nome
   
    class Meta:
        ordering = ['nome', 'email']
        db_table = 'pessoafisica'
       
class PessoaJuridica(Pessoa):
    razao_social = models.CharField("Razao Social", max_length=200)
    nome_fantasia = models.CharField("Nome Fantasia", max_length=200)
    cnpj = models.CharField("CNPJ",max_length=14,unique=True)
    ie = models.CharField("Inscricao Estadual",max_length=14,unique=True)
    dt_fundacao = models.DateTimeField("Data da Fundacao", auto_now_add=True)
    nome_prop = models.CharField(max_length=200, verbose_name='Nome do Proprietario')
    site = models.CharField("Site", max_length=200)
    contato = generic.GenericRelation(Contatos)
   
    def __unicode__(self):
        return self.razao_social
   
    class Meta:
        ordering = ['razao_social']
        db_table = 'pessoajuridica'


Model admin.py

from django.db import models
from django.contrib import admin
from grafica.cadastro.models import *

class GenericContatosInline(generic.GenericStackedInline):
    model = Contatos

class PessoaFisicaAdmin(admin.ModelAdmin):
    #Listagem com os campos id e nome
    list_display = ('id','nome', 'email')
    date_hierarchy = 'datacadastro'
    ordering = ['nome']
    list_filter = ('id','nome')
    search_fields = ('nome','cpf')

    #Pesquisa somente no campo nome
    #search_fields = ['nome']
   
#Registra o model no admin
admin.site.register(PessoaFisica, PessoaFisicaAdmin)

class PessoaJuridicaAdmin(admin.ModelAdmin):
    #Listagem com os campos id e nome
    list_display = ('id','razao_social')
   
    #Pesquisa somente no campo nome
    search_fields = ['id', 'razao_social']
    inlines = [GenericContatosInline] * Quando realizo o cadastro de Pessoa Juridica, é instaciado o cadastro para o Contato, ótimo, o problema é que fica disponivel para cadastrar 3 contatos, não deveria mostrar somente uma opção?

a tela fica com as seguintes informações para cadastro:

Exemplo:

Contatos

Contato 1#

campo1
campo2
campo2

Contato 3#

campo1
campo2
campo2

Contato 3#

campo1
campo2
campo2

   
#Registra o model no admin
admin.site.register(PessoaJuridica, PessoaJuridicaAdmin) 

class CidadesAdmin(admin.ModelAdmin):
    list_display = ('cidade', 'cod_cidade')
   
    search_fields = ['cidade', 'cod_cidade']
    
admin.site.register(Cidades,CidadesAdmin)

#class ContatosAdmin(admin.ModelAdmin):
    #list_display = ('nome', 'email')
   
    #search_fields = ['nome', 'email']
    
#admin.site.register(Contatos,ContatosAdmin)

class ProspectAdmin(admin.ModelAdmin):
    list_display = ('nome', 'email')
   
    search_fields = ['nome', 'email']
    
admin.site.register(Prospect, ProspectAdmin)

class FormaPagamentoAdmin(admin.ModelAdmin):
    #list_display = ('frm_pag')

    search_fields = ['frm_pag']
admin.site.register(FormaPagamento, FormaPagamentoAdmin)

Model Cotacoes

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from grafica.cadastro.models import *

DEF_STATUS = (
              ('AP', 'Aprovado'), ('PE', 'Pendente'), ('NA', 'Nao Aprovado')
              )
   
class RegistraCotacoes(models.Model):
    cliente = generic.GenericRelation(Pessoa) * Aqui esta a charada, eu preciso que este campo traga todos os clientes cadastrados tanto na tabela PessoaFisica quanto PessoaJuridica (para a realização da cotação é imprescindivel que o usuário tenha acesso a todos os clientes, independentemente de ser PF ou PJ) como minha classe Pessoa é abstrata, não consegui vincular as ids de PF e PJ para este campo, conto com uma ajuda para conseguir esta associação.
    status = models.DateField("Status", choices = DEF_STATUS, max_length=2)
    observacoes = models.TextField("Observacoes")
    prazo_entrega = models.DateField("Prazo de Entrega", max_length=100)
    frm_pag = generic.GenericRelation(FormaPagamento)
    data_aprov = models.DateTimeField("Data da Aprovacao", auto_now_add=True)
   
    def __unicode__(self):
        return self.id
   
    class Meta:
        ordering = ['data_aprov', 'status' ]
        db_table = 'cotacoes'


Cotacoes admin.py

from django.db import models
from django.contrib import admin
from grafica.cotacoes.models import *
   
* Como vou associar a PF e PJ no campo cliente, incluindo no admin?

class RegistraCotacoesAdmin(admin.ModelAdmin):
    list_display = ('data_aprov', 'status' )
   
    #Pesquisa somente no campo nome
    search_fields = ['data_aprov', 'status' ]
admin.site.register(RegistraCotacoes, RegistraCotacoesAdmin)



Qual seria a codificação ideal para esta solução que desejo? Sei que ha muitos proramadores DJango experientes que podem contribuir, obrigado.

Peço a todos a colaboração para chegarmos a condição ideal, com certeza esta solução de cadastro de Pessoas Fisicas e Juridicas com classe abstrata fazendo vinculo entre os cadastros de ambas as classes será muito util para muitos desenvolvedores DJango, assim que finalizarmos o código pode ser postado como documento de auxilio para outros programadores.

Agradeço desde já.


--

elton santos

unread,
Feb 28, 2013, 12:45:50 AM2/28/13
to django...@googlegroups.com, pabl...@gmail.com
Realmente, a solução desse problema seria muito útil pra mim tbm... :/

Matheus R.

unread,
Feb 28, 2013, 6:04:46 AM2/28/13
to django...@googlegroups.com, pabl...@gmail.com
Acredito que uma solução é criando apenas um model Pessoa, com os atributos comuns (nome,sobrenome,email) e os atributos CPF e CNPJ. Sendo que estes dois últimos podem ser nulos (null=True).
Depois, para separar isso, vc pode criar dois métodos no model, por exemplo: get_pessoas_fisicas() e get_pessoas_juridicas(). No model de cotações, é só criar a FK para o model Pessoa.


[]'s


2013/2/28 elton santos <elton.me...@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.
 
 

Reply all
Reply to author
Forward
0 new messages