Question

J'ai une application de pylônes et j'utilise Formencode et HTMLFill pour gérer mes formulaires. J'ai une gamme de champs de texte dans mon modèle (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>

Cependant, je n'arrive pas à comprendre comment valider ces champs. Voici l'entrée pertinente de mon schéma

yardage = formencode.ForEach(formencode.validators.Int())

J'essaie de valider que chacun de ces champs est un int. Cependant, aucune validation ne se produit pour ces champs.

METTRE À JOURComme demandé, voici le code de l'action de ce contrôleur. Je sais que cela fonctionnait car je peux valider d'autres champs de formulaire.

    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')

METTRE À JOURIl a été suggéré sur IRC que je change le nom des éléments de yardage[] à yardagePas de résultat. Ils devraient tous être INTS, mais mettre F dans l'un des éléments ne fait pas que cela ne soit pas valide. Comme je l'ai déjà dit, je suis en mesure de valider d'autres champs de formulaire. Ci-dessous, tout mon schéma.

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())
Était-ce utile?

La solution

Il s'avère que ce que je voulais faire n'était pas tout à fait correct.

Modèle:

<tr>
  <td>Yardage</td>
  % for hole in range(9):
  <td>${h.text('hole-%s.yardage'%(hole), maxlength=3, size=3)}</td>
  % endfor
</tr>

(Aurait dû se rendre dans une boucle pour commencer.) Vous remarquerez que le nom du premier élément deviendra hole-1.yardage. J'utiliserai alors Formmencode.variabledEcode pour transformer cela en dictionnaire. Cela se fait dans le

Schéma:

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())

Le trouschema va valider cela hole-#.par et hole-#.yardage sont les deux INTS et ne sont pas vides. formencode.ForEach me permet de postuler HoleSchema au dictionnaire que j'obtiens de passer variable_decode=True au @validate décorateur.

Voici la submit Action de mon

Manette:

@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!'

En utilisant le @validate Le décorateur permet un moyen beaucoup plus propre de valider et de remplir les formulaires. La variable_decode=True est très important ou le dictionnaire ne sera pas correctement créé.

Autres conseils

c.form_result = schema.to_python(request.params) - (without dict)

Cela semble bien fonctionner.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top