Formulários para Plone: um passeio pelo framework z3c.form

1,464 views

Published on

Todo desenvolvedor web sabe o trabalho que dá desenvolver formulários de qualidade para suas aplicações. Por esse motivo, praticamente todos os frameworks web fornecem algum tipo de geração de formulários automáticos e/ou componentes para faciltar a criação de formulários customizados.

No caso do Plone (o framework) não é diferente e o framework Archetypes já incluia nativamente a geração de formulários para seus tipos de conteúdo. Porém, além de ser complicado para customizar e debugar, existiam claros limites no que se poderia realizar com eles.

Durante o desenvolvimento do BlueBream Aplication Server (antigo Zope3), uma variedade de componentes foram desenvolvidos que hoje fazer parte do ZTK (Zope Tool Kit). Um desses componentes é o pacote zope.formlib, que justamente foi criado para possibilitar a criação automática de formulários para objetos de conteúdo (models) e também para definição de formulários customizados. Porém, apesar da grande melhoria, a customização do formulário, definição de novas widgets ainda não eram satisfatórios.

Com base da experiência e problemas do zope.formlib, que surgiu em 2007 o framework z3c,form. Após anos de amadurecimento, hoje ele está totalmente integrado ao Plone e atualmente é considerado a melhor opção para a criação de formulários. O z3c.form possui um excelente nível de maturidade, cobertura de testes e mais importante: documentação detalhada e grande flexibilidade, sem que isso torne o torne tão complexo e difícil de se aprender.

O objetivo dessa palestra e fornecer uma visão geral do framework e seus componentes, e realizar um passeio por exemplos de formulários desenvolvidos com z3c.form que demonstrem seus recursos e sua integração com Plone.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,464
On SlideShare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
14
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Formulários para Plone: um passeio pelo framework z3c.form

  1. 1. Formul´rios para Plone: um passeio pelo a framework z3c.formRud´ Porto Filgueiras - rudazz@gmail.com - @rudaporto a September 29, 2011
  2. 2. Agenda Introdu¸˜o ca Hist´ria o z3c.form Perguntas
  3. 3. Introdu¸˜o ca Por que formularios sao importantes? Como posso simplificar a cria¸ao de formularios? c Como posso melhorar o reuso? Como os formul´rios podem ser mais resistentes a falhas? a
  4. 4. CMFFormController Recursos: Cola que conecta scripts com formul´rios e vice-versa a Simplifica a codifica¸˜o de formul´rios / scripts para ca a manipular formul´rios a Gerencia a transi¸˜o entre formul´rios e scripts ca a Conponentes: Forms (.cpt), Validators(.vpy), Actions(Butt˜es), Scritps(.cpy), State o Problemas: Arquivos espalhados dificultam o entendimento do fluxo Cria¸˜o e exibi¸˜o de widgets n˜o s˜o tratadas ca ca a a N˜o funciona com ZCA packages / views a
  5. 5. zope.formlib Caracteristicas: pacote padr˜o do ZTK para cria¸ao de formularios a c formularios sao um tipo de BrowserPage (context, request) define classes reus´veis para cria¸˜o de formul´rios a ca a possui template padrao (plone.app.form overrrides) permite a customiza¸ao de widgets, actions, validators, etc c define o padr˜o update() e render() ao ser invocado a Problemas: Nivel de customiza¸ao e limitado para casos mais complexos c Nao e pensado para a definicao de formularios aninhados (pai e filho) Documenta¸ao escassa: ”luke use de force: read the source” c
  6. 6. z3c.form O objetivo geral do z3c.form e tornar o desenvolvimento de formul´rios o mais simples poss´ e ao mesmo tempo prover a ıvel hooks que permitam a customiza¸˜o dos formul´rios em qualquer ca a n´ de acordo com as necessidades reais de diferentes casos de ıvel uso. Principais componentes (m´dulos): o form formul´rios base: Form, AddForm, EditForm, a DisplayForm groups formul´rios compostos de grupos de campos a (fieldsets) subform formul´rios aninhados a field API para manipulal¸˜o dos campos do formul´rio ca a button API para manipula¸˜o dos bot˜es do formul´rio ca o a validator API de valida¸˜o dos dados do formul´rio ca a widget API de cria¸˜o das widgets ca action API para defini¸˜o e manipula¸˜o de actions handlers ca ca
  7. 7. z3c.form: processamento do formulario Elementos principais: self.request objeto representando a requis¸ao HTTP atual c self.context Item associado ao formul´rio de acordo com contexto a no qual ele foi invocado; self.getContent() Objeto retirado do contexto e que ser´ a manipulado pelo formul´rio a n˜o ser que a a ignoreContext seja definido como True; self.status A mensagem que ser´ exibida no topo da regi˜o do a a conte´do quando o formul´rio for renderizado. u a updateWidgets atualiza todas as widgets de acordo com os dados enviados updateActions invoca os actions handlers do formul´rio de acordo a com o bot˜o pressionados a render invoca o template padr˜o que gera o HTML do a formul´rio e retorna esse conte´do a u
  8. 8. Exemplo: Person Interface 1 import z o p e . i n t e r f a c e 2 import z o p e . schema 3 4 c l a s s IPerson ( zope . i n t e r f a c e . I n t e r f a c e ) : 5 6 i d = z o p e . schema . TextLine ( 7 t i t l e =u ID , 8 r e a d o n l y=True , 9 r e q u i r e d=True )1011 name = z o p e . schema . TextLine (12 t i t l e =u Name ,13 r e q u i r e d=True )1415 g e n d e r = z o p e . schema . C h o i c e (16 t i t l e =u Gender ,17 v a l u e s =( male , f e m a l e ) ,18 r e q u i r e d=F a l s e )19 ...
  9. 9. Exemplo: Person 1 from z o p e . schema . f i e l d p r o p e r t y import F i e l d P r o p e r t y 2 3 c l a s s Person ( o b j e c t ) : 4 z o p e . i n t e r f a c e . implements ( I P e r s o n ) 5 6 id = FieldProperty ( IPerson [ id ]) 7 name = F i e l d P r o p e r t y ( I P e r s o n [ name ] ) 8 gender = F i e l d P r o p e r t y ( IPerson [ gender ] ) 910 def init ( s e l f , i d , name , g e n d e r=None ) :11 s e l f . id = id12 s e l f . name = name13 i f gender :14 s e l f . gender = gender
  10. 10. Exemplo: PersonAddForm 1 from z 3 c . form import form , f i e l d 2 3 c l a s s PersonAddForm ( form . AddForm ) : 4 5 f i e l d s = f i e l d . Fields ( IPerson ) 6 7 def create ( s e l f , data ) : 8 return Person (** data ) 910 d e f add ( s e l f , o b j e c t ) :11 s e l f . context [ object . id ] = object1213 d e f nextURL ( s e l f ) :14 r e t u r n i n d e x . h t ml
  11. 11. Exemplo: processamento do formul´rio a1 from z 3 c . form . t e s t i n g import T e s t R e q u e s t23 request = TestRequest ()4 addForm = PersonAddForm ( app , r e q u e s t )5 addForm . u p d a t e ( ) Nesse momento, ocorre uma s´ria de a¸˜es: e co As widgets s˜o inicializadas de acordo com os campos a definidos no atributo fields do formul´rio a O atributo addForm.widgets ´ o widget manager que cont´m e e todas as widgets inicializdas Por´m n˜o s˜o criadas widgets para todos os campos: se o e a a dado n˜o estiver acess´ no objeto ou um se houver uma a ıvel configura¸˜o para ignorar esse campo ca
  12. 12. Exemplo: inicializa¸˜o das widgets ca V´rias informa¸˜es dos campos s˜o transferidas para as widgets, a co a mas podem ser alterados posteriormente:1 addForm . w i d g e t s [ age ]23 # f i e l d . t i t l e −> age . l a b e l4 age . l a b e l5 u Age 67 #f i e l d . r e q u i r e d −> age . r e q u i r e d8 age . r e q u i r e d9 False O pr´ximo passo ´ determinar o valor que deve ser exibido na o e widget, na seguinte ordem: O valor padr˜o definido no schema a O valor atual do objeto que est´ sendo manipulado a O valor armazenado no request, se o formul´rio ainda n˜o foi a a submetido ou ocorreu erros na valida¸˜o ca
  13. 13. Exemplo: propriedades das widgets A propriedade mode define se a widget ser´ renderizada para a edi¸˜o (input) ou visualiza¸˜o (display): ca ca1 age . mode2 input O modo da widget ´ inicializado seguindo a seguinte ordem (os e itens posteriores sobrescrevem os anteriores): O valor global definido no widget manager A permiss˜o do attributo do objeto que est´ sendo manipulado a a A flag readonly definida no schema O atributo mode definido no field Outras propriedades que podem ser customizadas na widget s˜o os a atributos: label e required.
  14. 14. Exemplo: encontrar um action manager e execut´-lo a O bot˜o ”Add” ´ ao mesmo tempo um action e um widget: a e1 l e n ( addForm . a c t i o n s )2 134 a d d A c t i o n = addForm . a c t i o n s [ add ]5 addAction . t i t l e6 u Add 78 addAction . value9 u Add O action handler do AddForm realiza sequencia de a¸oes: c chama o metodo create(data) passando os dados enviados no formulario chama o metodo add(object) com o resultado do create() redireciona para a URL retornada pelo metodo nextURL() se foi finalizada a cria¸˜o do novo objeto ca
  15. 15. Exemplo: form.AddForm.handleAdd 1 c l a s s AddForm ( Form ) : 2 ”””A f i e l d and b u t t o n b a s e d add form . ””” 3 z o p e . i n t e r f a c e . implements ( i n t e r f a c e s . IAddForm ) 4 i g n o r e C o n t e x t = True 5 i g n o r e R e a d o n l y = True 6 finishedAdd = False 7 8 @button . b u t t o n A n d H a n d l e r ( ( Add ) , name= add ) 9 d e f handleAdd ( s e l f , a c t i o n ) :10 data , e r r o r s = s e l f . e x t r a c t D a t a ( )11 if errors :12 s e l f . status = s e l f . formErrorsMessage13 return14 o b j = s e l f . createAndAdd ( data )15 i f o b j i s not None :16 # mark o n l y a s f i n i s h e d i f we17 # g e t t h e new o b j e c t18 s e l f . f i n i s h e d A d d = True
  16. 16. Exemplo: form.AddForm.createAndAdd 1 c l a s s AddForm ( Form ) : 2 ”””A f i e l d and b u t t o n b a s e d add form . ””” 3 z o p e . i n t e r f a c e . implements ( i n t e r f a c e s . IAddForm ) 4 i g n o r e C o n t e x t = True 5 i g n o r e R e a d o n l y = True 6 finishedAdd = False 7 8 # c u t ## # 910 d e f createAndAdd ( s e l f , d a t a ) :11 obj = s e l f . c r e a t e ( data )12 event = l i f e c y c l e e v e n t . ObjectCreatedEvent ( obj )13 zope . event . n o t i f y ( event )14 s e l f . add ( o b j )15 return obj
  17. 17. Exemplo: renderiza¸˜o do formulario PersonAddForm ca 1 >>> p r i n t addForm ( ) # u p d a t e ( ) e r e n d e r ( ) 2 <form a c t i o n=” . ”> 3 <d i v c l a s s=” row ”> 4 < l a b e l f o r=” form−w i d g e t s −i d ”>ID</ l a b e l> 5 <i n p u t t y p e=” t e x t ” i d=” form−w i d g e t s −i d ” 6 name=” form . w i d g e t s . i d ” 7 c l a s s=” t e x t −w i d g e t r e q u i r e d t e x t l i n e − f i e l d ” 8 v a l u e=” ” /> 9 </ d i v>10 . . .11 <d i v c l a s s=” a c t i o n ”>12 <i n p u t t y p e=” s u b m i t ”13 i d=” form−b u t t o n s −add ”14 name=” form . b u t t o n s . add ”15 c l a s s=” s u b m i t −w i d g e t16 b u t t o n − f i e l d ” v a l u e=”Add” />17 </ d i v>18 </ form>
  18. 18. Exemplo: form.EditForm 1 c l a s s EditForm ( Form ) : 2 ”””A s i m p l e e d i t form w i t h an a p p l y b u t t o n . ””” 3 z o p e . i n t e r f a c e . implements ( i n t e r f a c e s . I E d i t F o r m ) 4 5 s u c c e s s M e s s a g e = ( Data s u c c e s s f u l l y u p d a t e d . ) 6 noChangesMessage = ( No c h a n g e s were a p p l i e d . ) 7 8 @button . b u t t o n A n d H a n d l e r ( ( A p p l y ) , name= a p p l y ) 9 d e f ha n d l eA p p ly ( s e l f , a c t i o n ) :10 data , e r r o r s = s e l f . e x t r a c t D a t a ( )11 if errors :12 s e l f . status = s e l f . formErrorsMessage13 return14 changes = s e l f . applyChanges ( data )15 i f changes :16 s e l f . status = s e l f . successMessage17 else :18 s e l f . s t a t u s = s e l f . noChangesMessage
  19. 19. Exemplo: form.EditForm 1 c l a s s EditForm ( Form ) : 2 .. 3 d e f applyChanges ( s e l f , d a t a ) : 4 content = s e l f . getContent () 5 c h a n g e s = a p p l y C h a n g e s ( s e l f , c o n t e n t , d a t a ) #* * 6 # `` changes `` i s a d i c t i o n a r y ; 7 # i f empty , t h e r e were no c h a n g e s 8 i f changes : 9 # C o n s t r u c t change−d e s c r i p t i o n s10 # f o r t h e o b j e c t −m o d i f i e d e v e n t11 descriptions = []12 f o r i n t e r f a c e , names i n c h a n g e s . i t e m s ( ) :13 d e s c r i p t i o n s . append (14 lifecycleevent . Attributes ( interface ,15 * names ) )16 # Send o u t a d e t a i l e d o b j e c t −m o d i f i e d e v e n t17 event . n o t i f y (18 l i f e c y c l e e v e n t . ObjectModifiedEvent (19 content ,20 * descriptions ))21 return changes
  20. 20. z3c.form e a integra¸ao com Ploe:plone.app.z3cform c Para usar o template do pacote plone.app.z3c.form, ´ necess´rio e a registrar um novo skin Layer. No profile do seu produto, ao incluir plone.app.z3c.form como dependencia, ele automaticamente instala esse novo Layer e dessa forma teremos a valida¸ao in-line e c outras melhorias no template padrao: Arquivo: meuproduto/profiles/default/metadata.xml1 <m et a da t a>2 < v e r s i o n>1</ v e r s i o n>3 <d e p e n d e n c i e s>4 <dependency>5 p r o f i l e −p l o n e . app . z 3 c f o r m : d e f a u l t6 </ dependency>7 </ d e p e n d e n c i e s>8 </ m et a d a t a>
  21. 21. 1 from p l o n e . z 3 c f o r m . l a y o u t import w r a p f o r m 2 from z 3 c . form import form , f i e l d 3 4 c l a s s ApybMemberDisplayForm ( form . Form ) : 5 mode = d i s p l a y 6 f i e l d s = f i e l d . F i e l d s ( IApybMember ) . s e l e c t ( f u l l n a m e , 7 organization , email , c i t y , uf , type , 8 community relation ) 9 f i e l d s [ type ] . widgetFactory = radio . RadioFieldWidget10 l a b e l = ( u P e r f i l do Membro )11 d e s c r i p t i o n = ( u Segue a b a i x o o s d e t a l h e s12 do p e r f i l do membro : )13 ...1415 MemberDisplayFormView = w r a p f o r m ( ApybMemberDisplayForm )
  22. 22. 1 from p l o n e . z 3 c f o r m . l a y o u t import w r a p f o r m 2 from z 3 c . form import form , f i e l d 3 4 c l a s s ApybMemberDisplayForm ( form . Form ) : 5 .. 6 d e f getContent ( s e l f ) : 7 session = Session () 8 e m a i l = s e l f . r e q u e s t . g e t ( e m a i l , None ) 9 q u e r y s e s s i o n . q u e r y ( model . ApybMember )10 member = q u e r y . f i l t e r b y ( e m a i l=e m a i l )11 i f not member :12 status = IStatusMessage ( s e l f . request )13 message = ” C a d a s t r o de membro nao e n c o n t r a d o ”14 s t a t u s . a d d S t a t u s M e s s a g e ( message , type= i n f o )15 url = s e l f . context . absolute url ()16 return s e l f . request . response . r e d i r e c t ( u r l )17 else :18 r e t u r n member . one ( )1920 MemberDisplayFormView = w r a p f o r m ( ApybMemberDisplayForm )
  23. 23. z3c.form: alterando o template de renderiza¸˜o do caformulario1 # Do n o t mix w i t h :2 # Products . Five . browser ViewPageTemplateFile3 from z o p e . app . p a g e t e m p l a t e import ViewPageTemplateFile 4 as Z o p e 3 P a g e T e m p l a t e F i l e56 c l a s MyForm ( form . AddForm ) :7 ”””MyForm Example ”””8 t e m p l a t e = Z o p e 3 P a g e T e m p l a t e F i l e ( ”my−t e m p l a t e . p t ” )
  24. 24. z3c.form: alterando o template de renderiza¸˜o do caformulario1 # Do n o t mix w i t h :2 # Products . Five . browser ViewPageTemplateFile3 from z o p e . app . p a g e t e m p l a t e import ViewPageTemplateFile 4 as Z o p e 3 P a g e T e m p l a t e F i l e56 c l a s MyForm ( form . AddForm ) :7 ”””MyForm Example ”””8 t e m p l a t e = Z o p e 3 P a g e T e m p l a t e F i l e ( ”my−t e m p l a t e . p t ” )
  25. 25. Perguntas? Contato: Rud´ Porto Filgueiras a rudazz@gmail.com @rudaporto github.com/rudaporto

×