Adicionar Constraint ou Validar a existência de chave composta

39 views
Skip to first unread message

Leandro - ProfessionalIT

unread,
Sep 30, 2009, 10:30:29 AM9/30/09
to web2py-users-brazil
Pois é, não sei se o titulo está de acordo, mas vamos lá...

Tenho uma tabela chamada tabela_preco que tem os campos:

id
categoria_cliente_id
produto_id
preco

Bom, o que eu preciso é não permitir que seja inserido duas vezes
um preço para um mesmo produto de uma mesma categoria, por exemplo:

id - categoria - produto - preco
01 01 01 12,50
02 01 01 20,00 (isto não pode acontecer, pois
já tem um preço lançado para este produto nesta categoria)

Como implemento isso ?

Renato Caliari

unread,
Sep 30, 2009, 12:09:25 PM9/30/09
to web2py-us...@googlegroups.com
Se fosse apenas para a verificação de um campo podia implementar um "requires" no arquivo de definição da tabela, algo como:

db.tabela.campo.requires=[IS_NOT_IN_DB(db,'tabela.campo')]

Porém, no seu caso é uma constraint de múltiplos campos. Tenta testar uma variação deste tipo logo após a definição da tabela:

db.tabela.produto.requires=[IS_NOT_IN_DB(db(db.tabela.categoria==request.vars.categoria)),db.tabela.produto, error_message='produto já cadastrado nesta categoria')]

Depois informe qual a solução implementada.


2009/9/30 Leandro - ProfessionalIT <lsev...@gmail.com>

Renato-ES

unread,
Oct 1, 2009, 8:09:11 AM10/1/09
to web2py-users-brazil
Leandro,

Vi que o Massimo deu a mesma sugestão, na lista de discussão
internacional, de utilizar o "IS_NOT_IN_DB" mas você acabou preferindo
utilizar um validador no formulário.

A primeira solução não funcionou ou não era prático para o seu
projeto?

Abraços. :-)

OBS: No exemplo rápido que eu havia dado, percebi que faltaram os
finais "_id" nos nomes dos campos. Ex: tabela.categoria_id.


On 30 set, 13:09, Renato Caliari <caliari.ren...@gmail.com> wrote:
> Se fosse apenas para a verificação de um campo podia implementar um
> "requires" no arquivo de definição da tabela, algo como:
>
> db.tabela.campo.requires=[IS_NOT_IN_DB(db,'tabela.campo')]
>
> Porém, no seu caso é uma constraint de múltiplos campos. Tenta testar uma
> variação deste tipo logo após a definição da tabela:
>
> db.tabela.produto.requires=[IS_NOT_IN_DB(db(db.tabela.categoria==request.vars.categoria)),db.tabela.produto,
> error_message='produto já cadastrado nesta categoria')]
>
> Depois informe qual a solução implementada.
>
> 2009/9/30 Leandro - ProfessionalIT <lsever...@gmail.com>

ProfessionalIT

unread,
Oct 1, 2009, 10:58:54 AM10/1/09
to web2py-users-brazil
Oi Renato,

Realmente não funcionou pois implementando aquele validator eu não
conseguiria montar os combos(os html select) pois para isso eu preciso
do IS_IN_DB(). Bom, a solução que eu implemetei resolve este meu
problema perfeitamente, pois impede de ser cadastrada um novo preço
com uma mesma categoria e produto. Realmente a possibilidade de
implementar funções pré-validação(onvalidation) e pré salvamento
(onaccepts) no método crud.create te da uma gama de possibilidades
muito interessante.

De qualquer maneira muito obrigado pela a tua ajuda.

O Web2Py é realmente muito poderoso.

Um abraço,
Leandro.

Renato Caliari

unread,
Oct 1, 2009, 11:51:18 AM10/1/09
to web2py-us...@googlegroups.com

Legal Leandro! :-)

Só uma questão: atrelando o validador apenas ao form em específico não poderia ser problemático você tentar adicionar um registro nesta tabela em outro lugar do sistema e esquecer de usar o validador?


Como complemento: navegando no grupo internacional achei um jeito que o próprio Massimo havia sugerido em outro tópico.

O usuário tknack estava na mesma situação que a sua quanto a não aparece a lista de seleção (combos) quando utilizados os dois validadores no requires:
..."when I try to use IS_NOT_IN_DB with IS_IN_DB, I can't obtain a drop down list, even if I change the order of the lines."

Sugestão dada pelo Massimo:

class MY_ODD_VALIDATOR(IS_IN_DB):
     def __init__(self,*a,**b): IS_IN_DB.__init__(self,*a,**b)
     def __call__(self,value):
           e=IS_IN_DB.__call__(self,value)
           if e[1]: return e
           e=IS_NOT_IN_DB(db
(db.u.unit_id==request.vars.unit_id),'u.zd_id')(value)
           return e

db.u.zd_id.requires=MY_ODD_VALIDATOR(db,'zonedef.id','%(nom)s')


Fonte: http://groups.google.com/group/web2py/browse_thread/thread/133644f67efdc217


Acho bom colocarmos o link para rastrear o mesmo tópico que você abriu no grupo internacional para auxiliar outros que possam ter a mesma dúvida e encontrar as outras opiniões:
 http://groups.google.com/group/web2py/browse_thread/thread/943721afbfc6b173/3e8887ffe85c1508?hl=en&lnk=gst&q=+Multiple+fields+in+a+constraint+#3e8887ffe85c1508

Abraços! :-)


2009/10/1 ProfessionalIT <lsev...@gmail.com>

ProfessionalIT

unread,
Oct 1, 2009, 2:24:03 PM10/1/09
to web2py-users-brazil
Renato,

Tentei seguir esse exemplo implementando este validator e ele
funciona !, mas tem um pequeno detalhe, funciona perfeitamente para o
método crud.create, mas para o método crud.update valida e não deixa a
operação continuar porque logicamente o registo existe. Então acho que
a minha solução está mais adequada. Quanto a possibilidade de inserir
um registro em outro lugar no sistema, não existe pois esta é
realmente a rotina de inclusão/atualização dos registros da tabela de
preço.

Renato-ES

unread,
Oct 1, 2009, 4:31:04 PM10/1/09
to web2py-users-brazil
Hmmm, entendi. E se colocar alguma coisa dentro daquele validator que
o Massimo mandou para pesquisar apenas os registros diferentes do ID
atual? Algo como:

IS_NOT_IN_DB(db((tabela.categoria_id==request.vars.categoria_id)&&
(tabela.id!=request.vars.id)),'tabela.produto_id')

Assim evitaria dele pesquisar o próprio registro.

Sei que já resolveu seu problema mas é termos alternativas. :-)

ProfessionalIT

unread,
Oct 2, 2009, 9:00:24 AM10/2/09
to web2py-users-brazil
Não rola Renato, porque no create o meu objeto não tem um id ainda
e ao executar da o erro:
AttributeError: 'function' object has no attribute 'id'

Realmente acho que a minha solução ainda é a melhor.

De qualquer maneira, te agradeço muito.
Um grande abraço.
Leandro.

Renato-ES

unread,
Oct 2, 2009, 11:30:55 AM10/2/09
to web2py-users-brazil
Hehe, beleza. Teria que verificar dentro do validador customizado se
há o objeto ID para então fazer a comparação.

O que importa é o problema foi resolvido. :-)

Abraços!
Reply all
Reply to author
Forward
0 new messages