Zope+Plone+Mysql = Produtividade Máxima!
Montando o formulário
Para montar um formulário, crie um documento chamado
Controller Page Template. Esse documento irá servir para a criação de
nossos formulários. Veja:

Clique em Add and Edit. Dessa forma, você adiciona um CPT (controller page template).
O que é Controller Page Template?
Controller Page Template é um sistema de templates que
utiliza o ZPT (Zope Page Templates) para gerenciar formulários. O
sistema funciona da forma em que você define uma ação e uma validação
para o formulário, fazendo dessa forma com que o formulário seja
validado e baseado em sua resposta ele determinar a ação a ser dada.
Todos os formulários escritos usando o CPT tem uma estrutura básica semelhante a essa abaixo:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<metal:block fill-slot="top_slot"
tal:define="dummy python:request.set('disable_border',1)" />
<head>
<title tal:content="template/title">The title</title>
</head>
<body>
<div metal:fill-slot="main"
tal:define="errors options/state/getErrors;">
<form method="POST"
tal:attributes="action
string:${here/absolute_url}/${template/id};">
<p><input
type="submit" name="form.button.submit" value="Submit" /></p>
<input type="hidden" name="form.submitted" value="1" />
</form>
</div>
</body>
</html>
Essa é uma estrutura básica de formulário. Dentro das tags <div></div> que iniciaremos os formulários.
CPT parte a parte
Na estrutura acima, nós vimos que um formulário básico de cpt tem várias partes a serem cobertas, e cada tag ali usada tem um objetivo. Vamos ver cada umas delas agora:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
Este bloco de marcações tem como objetivo indicar que esse template é um arquivo xhtml e que está no domínio de tradução do Plone. O uso de i18 é com frequencia utilizado para realização de tradução de aplicações, que não é o nosso caso. Também realiza a chamada ao main_template do Plone, permitindo que nosso formulário use a engine de templates do Plone.
<metal:block fill-slot="top_slot"
tal:define="dummy python:request.set('disable_border',1)" />
Este bloco de código tem como objetivo remover as bordas de edições do template no Plone, fazendo assim com que a aplicação seja mais transparente possível para o usuário.
<head>
<title tal:content="template/title">The title</title>
</head>
<body>
Este bloco de código é parte obrigatória do html, e o comando tal acima, faz parte do ZPT
<div metal:fill-slot="main"
tal:define="errors options/state/getErrors;">
Faz a chamada ao slot main do main_template e define a variável errors para o estado de erros do formulário.
<form method="POST" tal:attributes="action string:${here/absolute_url}/${template/id};">
Definição do form, onde ele manda o action para o próprio template. Isso é necessário para o CPT gerenciar as validações e suas ações.
<p><input type="submit" name="form.button.submit" value="Submit" /></p>
<input type="hidden" name="form.submitted" value="1" />
Esses dois input's são necessários para que o mecanismo do CPT funcione.
Fazendo o formulário
Para a criação do formulário de clientes, nós devemos utilizar algumas marcações em especial para podermos visualizar os campos que contém erro. Veja:
<div class="field"
tal:define="error errors/rg_cliente|nothing;"
tal:attributes="class python:test(error, 'field error', 'field')">
<label for="rg_cliente">RG do Cliente</label>
<span class="fieldRequired" title="Necessário">(Necessário)</span>
<div class="formHelp">
Informe o RG do cliente
</div>
<div tal:content="error">Saida do Erro</div>
<input type="text"
id="rg_cliente"
name="rg_cliente"
size="15"
tabindex=""
tal:attributes="value request/rg_cliente | nothing;
tabindex tabindex/next;"
/>
</div>
O que nós fazemos nesse exemplo é criar uma classe que irá colorir nosso campo do formulário caso esse esteja errado, e pegar o valor do formulário quando esse precisar ser corrigido.
Faça o mesmo que o exemplo acima para os demais campos do cadastro de cliente, substituindo o rg_cliente pelos nomes dos outros campos. Os nomes são:
rg_cliente
inscricao_estadual_cliente
cpf_cnpj_cliente
endereco_cliente
bairro_cliente
codigo_postal_cliente
cidade_cliente
uf_cliente
data_nascimento_cliente
telefone_cliente
celular_cliente
email_cliente
informacoes_cliente
Note que o campo de id_cliente não está sendo feito porque isso é apenas um controle do banco de dados, e não será inserido por nós.
O arquivo completo esta em anexo, mas não foi totalmente completo. Quem quiser completar ele, seria muito bom :-)