Log in |
Construir uma lista de itens e pre�os (zclass e zcatalog)It's a portuguese how-to teaching about zclasses and zcatalog. It's based on kedai " How-To: Build a simple ZClass ", but not is an translation. O produto em quest�o foi desenvolvido por Thiago e H�lio para a Escola de Veterin�ria da UFMG. O objetivo era criar uma lista de itens e pre�os que pudesse ser pesquisada e que fosse facilmente administrada. Considera��esAssumimos que voc� tem bom conhecimento do Zope, sendo desnecess�ria a explica��o minuciosa dos passos apresentados. Utilizamos Zope 2.3.2, em um sistema operacional Linux, para o desenvolvimento. Vers�es anteriores n�o devem ser problema, entretanto. MetasAo fim desse Como-Fazer, teremos um objeto PrecosFolder, que guardar� objetos PrecosItem, e um cat�logo desses itens. Teremos tamb�m um m�todo para apresentar os itens e seus pre�os numa tabela, bem como um formul�rio de busca e um m�todo para apresentar os resultados em um ou mais PrecosFolder. O que faremos:
1. Criar as classesEm 'Control_Panel/Products', adicione um novo produto ('Add Product') com Id "PrecosFolder" e Title "Lista de Pre�os". Dentro do produto PrecosFolder rec�m criado adicione uma nova zclass. Preencha com "PrecosFolder" o Id, o Title e o Meta Type. Para que a nova classe possa conter objetos, selecione 'ZClasses:ObjectManager' como classe base. Certifique-se para que as op��es 'Create constructor objects?' e 'Include Standard Zope persistent object base classes?' estejam marcadas. Clique em 'Add'. Voc� ter� criado a classe PrecosFolder e seus construtores. Entre na classe PrecosFolder que voc� criou e adicione, novamente, uma zclass. Preencha Id, Title e Meta Type com "PrecosItem". Deixe marcadas as op��es 'Create constructor objects?' e 'Include Standard Zope persistent object base classes?'. Selecione 'ZCatalog: CatalogAware' como classe base. Isso permitir� que PrecosItem seja indexada pelo cat�logo que iremos criar na inst�ncia de PrecosFolder. Clique em 'Add'. Como resultado voc� obter� a seguinte estrutura: 2. Adicionar propriedades personalizadasDentro da classe PrecosFolder, clique na aba 'Property Sheets' e em 'Add Common Instance Property Sheet'. Preencha o Id com "PrecosFolder" e clique em 'Add'. Entre na rec�m criada folha de propriedades PrecosFolder e adicione o seguinte:
Dentro da classe PrecosItem, de forma semelhante � ilustrada acima, adicione o seguinte � folha de propriedades PrecosItem da classe PrecosItem:
3. Modificar os scripts de constru��o de PrecosFolderTudo o que precisamos fazer � modificar o formul�rio e o m�todo que constroem o objeto para que as propriedades sejam adequadamente preenchidas e para que um zcatalog seja criado automaticamente. 3.1. Editar as propriedadesSubstitua o conte�do de PrecosFolder_addForm por: <html> <head><title>Adicionar PrecosFolder</title></head> <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> <h2>Adicionar PrecosFolder</h2> <form action="PrecosFolder_add"> <table> <tr> <th>Id</th> <td><input type="text" name="id" /></td> </tr> <tr> <th>Titulo</th> <td><input type="text" name="title" /></td> </tr> <tr> <td colspan="2"> <input type="submit" value=" Adicionar " /> </td> </tr> </table> </form> </body> </html> Agora vamos modificar o m�todo inicial para que o objeto tenha o t�tulo que foi inclu�do no formul�rio. Substitua o conte�do de PrecosFolder_add por: <html> <head><title>Adicionar PrecosFolder</title></head> <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> <dtml-with "PrecosFolder.createInObjectManager(REQUEST['id'], REQUEST)"> <dtml-call "propertysheets.PrecosFolder.manage_editProperties(REQUEST)"> </dtml-with> <dtml-if DestinationURL> <dtml-call "RESPONSE.redirect(DestinationURL+'/manage_workspace')"> <dtml-else> <dtml-call "RESPONSE.redirect(URL2+'/manage_workspace')"> </dtml-if> </body> </html> Explicando: 3.2. Criando um zcatalogAdicione o seguinte c�digo a PrecosFolder_add no primeiro
<dtml-call "manage_addProduct['ZCatalog'].manage_addZCatalog('catalogoItens','', 'create_default_catalog_',REQUEST)"> <dtml-with "catalogoItens"> <dtml-call "manage_delColumns(['summary',],REQUEST,RESPONSE,URL1)"> <dtml-call "manage_addColumn('nome',REQUEST,RESPONSE,URL1)"> <dtml-call "manage_addColumn('preco',REQUEST,RESPONSE,URL1)"> <dtml-call "manage_addIndex('nome','TextIndex',REQUEST,RESPONSE,URL1)"> </dtml-with> 4. Modificar os scripts de constru��o de PrecosItemPrecosItem exige uma abordagem mais complicada. Para facilitar a administra��o, optamos por criar Ids automaticamente a partir do nome dado ao item. Como usamos acentua��o e o Id precisa ser compat�vel com o padr�o para URLs, fizemos um script para retirar todos os acentos e caracteres n�o padr�o. Al�m disso, no ato da inclus�o, editaremos as propriedades do objeto e o incluiremos no zcatalog. 4.1. Criar um Id automaticamenteVamos criar um script python chamado "ide" dentro da classe PrecosFolder, para que possa ser utilizado pelo m�todo PrecosItem_add. Preencha 'Parameter List' com "nome" e o corpo do script com: id='' dicionario={' ' : '_', '!' : '_', '"' : '_', '#' : '_', '$' : '_', '%' : '_', '&' : '_', '\'' : '_', '(' : '_', ')' : '_', '*' : '_', '+' : '_', ',' : '_', '-' : '_', '.' : '_', '/' : '_', '0' : '0', '1' : '1', '2' : '2', '3' : '3', '4' : '4', '5' : '5', '6' : '6', '7' : '7', '8' : '8', '9' : '9', ':' : '_', ';' : '_', '<' : '_', '=' : '_', '>' : '_', '@' : '_', 'A' : 'a', 'B' : 'b', 'C' : 'c', 'D' : 'd', 'E' : 'e', 'F' : 'f', 'G' : 'g', 'H' : 'h', 'I' : 'i', 'J' : 'j', 'K' : 'k', 'L' : 'l', 'M' : 'm', 'N' : 'n', 'O' : 'o', 'P' : 'p', 'Q' : 'q', 'R' : 'r', 'S' : 's', 'T' : 't', 'U' : 'u', 'V' : 'v', 'W' : 'w', 'X' : 'x', 'Y' : 'y', 'Z' : 'z', '[' : '_', '\\' : '_', ']' : '_', '^' : '_', '_' : '_', '`' : ' ', 'a' : 'a', 'b' : 'b', 'c' : 'c', 'd' : 'd', 'e' : 'e', 'f' : 'f', 'g' : 'g', 'h' : 'h', 'i' : 'i', 'j' : 'j', 'k' : 'k', 'l' : 'l', 'm' : 'm', 'n' : 'n', 'o' : 'o', 'p' : 'p', 'q' : 'q', 'r' : 'r', 's' : 's', 't' : 't', 'u' : 'u', 'v' : 'v', 'w' : 'w', 'x' : 'x', 'y' : 'y', 'z' : 'z', '{' : '_', '|' : '_', '}' : '_', '~' : '_', ',' : '_', '^' : '_', '*' : '_', '-' : '_', '-' : '_', '~' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : '_', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'ae', '�' : 'c', '�' : 'e', '�' : 'e', '�' : 'e', '�' : 'e', '�' : 'i', '�' : 'i', '�' : 'i', '�' : 'i', '�' : '_', '�' : 'n', '�' : 'o', '�' : 'o', '�' : 'o', '�' : 'o', '�' : 'o', '�' : '_', '�' : '_', '�' : 'u', '�' : 'u', '�' : 'u', '�' : 'u', '�' : 'y', '�' : '_', '�' : '_', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'a', '�' : 'ae', '�' : 'c', '�' : 'e', '�' : 'e', '�' : 'e', '�' : 'e', '�' : 'i', '�' : 'i', '�' : 'i', '�' : 'i', '�' : '_', '�' : 'n', '�' : 'o', '�' : 'o', '�' : 'o', '�' : 'o', '�' : 'o', '�' : '_', '�' : '_', '�' : 'u', '�' : 'u', '�' : 'u', '�' : 'u', '�' : 'y', '�' : '_', '�' : 'y', 'Y' : 'y'} for letra in nome: id = id + dicionario[letra] return id N�o se preocupe, criamos quase toda a tabela ascii para voc�... � s� copiar :) 4.2. Editar as propriedadesSubstitua o conte�do de PrecosItem_addForm por: <html> <head><title>Adicionar PrecosItem</title></head> <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> <h2>Adicionar PrecosItem</h2> <form action="PrecosItem_add"> <table> <tr><th>Item</th> <td><input type="text" name="nome" /></td> </tr> <tr><th>Pre�o</th> <td><input type="text" name="preco" /></td> </tr> <tr><td colspan="2" align="center"> <input type="submit" value=" Adicionar " /> </td></tr> </table> </form> </body> </html> Substitua o conte�do de PrecosItem_add por: <html> <head><title>Adicionar PrecosItem</title></head> <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> <dtml-call "REQUEST.set('id',ide(nome))"> <dtml-with "PrecosItem.createInObjectManager(REQUEST['id'], REQUEST)"> <dtml-call "propertysheets.PrecosItem.manage_editProperties(REQUEST)"> </dtml-with> <dtml-if DestinationURL> <dtml-call "RESPONSE.redirect(DestinationURL+'/manage_workspace')"> <dtml-else> <dtml-call "RESPONSE.redirect(URL2+'/manage_workspace')"> </dtml-if> </body> </html> Acabamos de possibilitar a cria��o de itens com seus respectivos nome e
pre�o. Como precisamos de um Id, o criamos partir do nome, alterando os
caracteres especiais. Isso foi feito na linha
4.3. Catalogar automaticamente os itensInsira , entre as tagsdtml-with "PrecosItem.createInObjectManager(REQUEST['id'], REQUEST)" e /dtml-with o seguinte c�digo:
<dtml-call "manage_editCataloger('catalogoItens')"> <dtml-call reindex_object> 5. Permitir edi��o dos objetosComo criamos propriedades personalizadas tanto para PrecosFolder quanto para PrecosItem, teremos que alterar tamb�m as abas do Zope que aparecem quando clicamos numa inst�ncia do objeto. No caso de PrecosItem, teremos que criar um formul�rio e um m�todo capazes de recatalogar a inst�ncia editada.5.1. Determinar quais abas do Zope ser�o exibidasAntes de definir as abas, vamos definir um m�todo padr�o de exibi��o (e que ser� utilizado como a aba 'View'). Dentro da classe PrecosFolder, crie um m�todo com Id "index_html": <dtml-var standard_html_header> <dtml-var MostrarTabela> <dtml-var standard_html_footer> O m�todo MostrarTabela ser� criado posteriormente. Optamos por mant�-lo como um m�todo separado pois poder� ser reutilizado em outros casos. Dentro da classe PrecosFolder, clique na aba 'Views'. Por padr�o haver� apenas "Contents". Adicionaremos as seguintes:
Poderemos assim administrar todas as caracter�sticas de PrecosFolder, incluindo permiss�es de acesso e capacidade de desfazer mudan�as. 5.2. Recatalogar o item ap�s edi��oPara PrecosItem, entretanto, o formul�rio padr�o 'propertysheets/PrecosItem/manage' n�o � suficiente, j� que n�o reindexa o item no zcatalog. Dentro da classe PrecosItem, adicione um m�todo com Id "PrecosItemEditForm": <dtml-var manage_page_header> <dtml-var manage_tabs> <form action="PrecosItemEdit"> <table> <tr><th>Item</th> <td><input type="text" name="nome" value="&dtml-nome;" /></td> </tr> <tr><th>Pre�o</th> <td><input type="text" name="preco" value="&dtml-preco;" /></td> </tr> <tr><td colspan="2" align="center"> <input type="submit" value=" Editar " /> </td></tr> </table> </form> <dtml-var manage_page_footer> Adicione, com Id "PrecosItemEdit", o m�todo que processar� o formul�rio acima: <html> <head><title>Edit PrecosItem</title></head> <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> <dtml-call "propertysheets.PrecosItem.manage_editProperties(REQUEST)"> <dtml-call "manage_editCataloger('catalogoItens')"> <dtml-call reindex_object> <dtml-if DestinationURL> <dtml-call "RESPONSE.redirect(DestinationURL+'/manage_workspace')"> <dtml-else> <dtml-call "RESPONSE.redirect(URL2+'/manage_workspace')"> </dtml-if> </body> </html> Dentro da classe PrecosItem, clique na aba 'Views'. Por padr�o haver� "Undo", "Ownership" e "Security". Apague se desejar. Adicionaremos apenas:
6. Criar visualiza��es padr�o para os objetosFalta criar o m�todo MostrarTabela, dentro da classe PrecosFolder, e ensinar como criar um formul�rio de busca. Dentro da classe PrecosFolder, crie um m�todo com Id "MostrarTabela" (modifique as cores segundo sua conveni�ncia): <table width="100%" border="0" align="center" cellspacing="0"> <tr><td align="center" bgcolor="#5f633d" colspan="2"> <b><dtml-var title_or_id></b> </td></tr> <dtml-in catalogoItens sort=id> <dtml-if sequence-odd> <tr bgcolor="#ffffff"> <dtml-else> <tr> </dtml-if> <td align="left" valign="top"><dtml-var nome></td> <td align="right" valign="top"><dtml-var preco></td> </tr> </dtml-in> </table> Como dissemos anteriormente, esse m�todo MostrarTabela poderia ser reutilizado. Ele ser� �til para mostrar os resultados de uma busca. Dentro da classe PrecosFolder, crie um m�todo com Id "searchResults": <dtml-call "REQUEST.set('nome', chaveBusca(txtbusca))"> <dtml-var MostrarTabela> O m�todo searchResults utiliza um pequeno script python com Id "chaveBusca" cujo objetivo � acrescentar "*s" �s palavras da busca. Crie-o, com "entrada" como 'Parameter': from string import split, rstrip chaves=split(entrada) chave='' for i in chaves: chave=chave+i+'* ' rstrip(chave) return chave 7. TestarAgora crie inst�ncias de PrecosFolder. Note que cada uma delas j� cont�m um zcatalog. Crie inst�ncias de PrecosItems para suas PrecosFolders. Note que elas s�o catalogadas automaticamente. Altere os pre�os de seus itens e veja o que acontece com o cat�logo. Caso voc� deseje ter uma p�gina exibindo todas as listas de pre�o, coloque os seguintes documentos e m�todos no mesmo diret�rio de suas PrecosFolders: index_html <dtml-var standard_html_header> <h1>Listas de pre�os</h1> <table width="100%" border="0" align="center"> <tr> <td align="center" bgcolor="#5f633d" class="cab" colspan="2">Listas</td> </tr> <dtml-with expr="PARENTS[0]"> <dtml-in expr="objectValues('PrecosFolder')" sort=title> <tr><td> <a href="&dtml-absolute_url;"><dtml-var title_or_id></a> </td></tr> </dtml-in> </dtml-with> <tr><td align="right"><a href="manage">[editar]</a></td></tr> <tr><td align="center"> <form action="Results" method="get"> <b>Item:</b> <input name="txtbusca" width="30" value="" /> <input type="SUBMIT" name="SUBMIT" value="Procurar" /> </form> </td></tr> </table> <dtml-var standard_html_footer> Results <dtml-var standard_html_header> <dtml-comment> Faz a busca em todos os itens do tipo PrecosFolder cont�guos. </dtml-comment> <dtml-in "objectValues('PrecosFolder')" sort=title> <dtml-var searchResults> <br /> <br /> </dtml-in "objectValues('PrecosFolder')"> <dtml-var standard_html_footer> Mais...Por quest�es est�ticas, seria interessante acrescentar �cones aos objetos que criamos (aqui usamos e . Para isso, entre em '/Control_Panel/Products/PrecosFolder', clique na aba 'Basic', clique em 'Browse...' e selecione uma figura em formato gif 16x16 para dar upload. Fa�a o mesmo para PrecosItem. Futuramente alteraremos as permiss�es de seguran�a de PrecosFolder automaticamente para que usu�rios do tipo owner possam adicionar, editar e excluir itens. |