Pilões formados com uma variedade de elementos de formulário
-
13-09-2019 - |
Pergunta
Eu tenho um aplicativo Pylons e estou usando o FormEncode e o HTMLFill para lidar com meus formulários. Eu tenho uma variedade de campos de texto no meu modelo (mako)
<tr> <td>Yardage</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> <td>${h.text('yardage[]', maxlength=3, size=3)}</td> </tr>
No entanto, não consigo descobrir como validar esses campos. Aqui está a entrada relevante do meu esquema
yardage = formencode.ForEach(formencode.validators.Int())
Estou tentando validar que cada um desses campos é uma int. No entanto, nenhuma validação ocorre para esses campos.
ATUALIZARConforme solicitado aqui é o código para a ação deste controlador. Eu sei que estava funcionando, pois posso validar outros campos de forma.
def submit(self): schema = CourseForm() try: c.form_result = schema.to_python(dict(request.params)) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} c.heading = 'Add a course' html = render('/derived/course/add.html') return htmlfill.render( html, defaults = c.form_result, errors = c.form_errors ) else: h.redirect_to(controler='course', action='view')
ATUALIZARFoi sugerido no IRC que eu mudei o nome dos elementos de yardage[]
para yardage
Nenhum resultado. Todos devem ser ints, mas colocar F em um dos elementos não faz com que seja inválido. Como eu disse antes, sou capaz de validar outros campos de forma. Abaixo está todo o meu esquema.
import formencode class CourseForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'}) par = formencode.ForEach(formencode.validators.Int()) yardage = formencode.ForEach(formencode.validators.Int())
Solução
Acontece que o que eu queria fazer não estava certo.
Modelo:
<tr>
<td>Yardage</td>
% for hole in range(9):
<td>${h.text('hole-%s.yardage'%(hole), maxlength=3, size=3)}</td>
% endfor
</tr>
(Deveria ter feito isso em um loop para começar.) Você notará que o nome do primeiro elemento se tornará hole-1.yardage
. Vou então usar FormEncode.variabledecode
para transformar isso em um dicionário. Isso é feito no
Esquema:
import formencode
class HoleSchema(formencode.Schema):
allow_extra_fields = False
yardage = formencode.validators.Int(not_empty=True)
par = formencode.validators.Int(not_empty=True)
class CourseForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'})
hole = formencode.ForEach(HoleSchema())
O Holeschema vai validar que hole-#.par
e hole-#.yardage
são INTs e não estão vazios. formencode.ForEach
Permite -me aplicar HoleSchema
para o dicionário que recebo de passar variable_decode=True
para o @validate
decorador.
Aqui está o submit
ação do meu
Controlador:
@validate(schema=CourseForm(), form='add', post_only=False, on_get=True,
auto_error_formatter=custom_formatter,
variable_decode=True)
def submit(self):
# Do whatever here.
return 'Submitted!'
Usando o @validate
O decorador permite uma maneira muito mais limpa de validar e preencher os formulários. o variable_decode=True
é muito importante ou o dicionário não será criado corretamente.
Outras dicas
c.form_result = schema.to_python(request.params) - (without dict)
Parece funcionar bem.