Comment rendre mon sélectionnez le champ avec WTForms?
J'ai un champ de sélection de qui a certains éléments délavé et des personnes handicapées, qui je tiens à rendre avec WTForms:
<select name="cg" id="cat" class="search_category">
<option value='' >{% trans %}All{% endtrans %}</option>
<option value='' style='background-color:#dcdcc3' id='cat1' disabled="disabled">-- {% trans %}VEHICLES{% endtrans %} --</option>
<option value='2' {% if "2" == cg %} selected="selected" {% endif %} id='cat2' >{% trans %}Cars{% endtrans %}</option>
<option value='3' {% if "3" == cg %} selected="selected" {% endif %} id='cat3' >{% trans %}Motorcycles{% endtrans %}</option>
<option value='4' {% if "4" == cg %} selected="selected" {% endif %} id='cat4' >{% trans %}Accessories & Parts{% endtrans %}</option>
...
J'ai une classe de formulaire qui fonctionne et j'ai commencé à mettre en œuvre pour localisées variable de catégorie mais je ne sais pas comment faire le widget(?) qui rend la délavé (background-color:#dcdcc3
) et les handicapés attributs d'un élément option:
class AdForm(Form):
my_choices = [('1', _('VEHICLES')), ('2', _('Cars')), ('3', _('Bicycles'))]
name = TextField(_('Name'), [validators.Required(message=_('Name is required'))], widget=MyTextInput())
title = TextField(_('title'), [validators.Required(message=_('Subject is required'))], widget=MyTextInput())
text = TextAreaField(_('Text'),[validators.Required(message=_('Text is required'))], widget=MyTextArea())
phonenumber = TextField(_('Phone number'))
phoneview = BooleanField(_('Display phone number on site'))
price = TextField(_('Price'),[validators.Regexp('\d', message=_('This is not an integer number, please see the example and try again')),validators.Optional()] )
password = PasswordField(_('Password'),[validators.Optional()], widget=PasswordInput())
email = TextField(_('Email'), [validators.Required(message=_('Email is required')), validators.Email(message=_('Your email is invalid'))], widget=MyTextInput())
category = SelectField(choices = my_choices, default = '1')
def validate_name(form, field):
if len(field.data) > 50:
raise ValidationError(_('Name must be less than 50 characters'))
def validate_email(form, field):
if len(field.data) > 60:
raise ValidationError(_('Email must be less than 60 characters'))
def validate_price(form, field):
if len(field.data) > 8:
raise ValidationError(_('Price must be less than 9 integers'))
Je peux utiliser la variable de catégorie à partir de ci-dessus pour rendre une sélection des catégories. Je tiens également à activer l'affichage spécial ie désactivé éléments et fondu d'arrière-plan. Pouvez-vous me dire comment je dois faire?
Merci
Mise à jour
Lorsque vous essayez la solution à partir de la réponse d'ajouter les personnes handicapées de l'attribut, j'obtiens ce message d'erreur:
Trace:
Traceback (most recent call last):
File "/media/Lexar/montao/lib/webapp2/webapp2.py", line 545, in dispatch
return method(*args, **kwargs)
File "/media/Lexar/montao/montaoproject/i18n.py", line 438, in get
current_user=self.current_user,
File "/media/Lexar/montao/montaoproject/main.py", line 469, in render_jinja
self.response.out.write(template.render(data))
File "/media/Lexar/montao/montaoproject/jinja2/environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "/media/Lexar/montao/montaoproject/templates/insert_jinja.html", line 221, in top-level template code
{{ form.category|safe }}
ValueError: need more than 2 values to unpack
Le code que j'ai essayé était:
from wtforms.widgets import html_params
class SelectWithDisable(object):
"""
Renders a select field.
If `multiple` is True, then the `size` property should be specified on
rendering to make the field useful.
The field must provide an `iter_choices()` method which the widget will
call on rendering; this method must yield tuples of
`(value, label, selected, disabled)`.
"""
def __init__(self, multiple=False):
self.multiple = multiple
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = 'multiple'
html = [u'<select %s>' % html_params(name=field.name, **kwargs)]
for val, label, selected, disabled in field.iter_choices():
html.append(self.render_option(val, label, selected, disabled))
html.append(u'</select>')
return HTMLString(u''.join(html))
@classmethod
def render_option(cls, value, label, selected, disabled):
options = {'value': value}
if selected:
options['selected'] = u'selected'
if disabled:
options['disabled'] = u'disabled'
return HTMLString(u'<option %s>%s</option>' % (html_params(**options), escape(unicode(label))))
class SelectFieldWithDisable(SelectField):
widget = SelectWithDisable()
def iter_choices(self):
for value, label, selected, disabled in self.choices:
yield (value, label, selected, disabled, self.coerce(value) == self.data)
class AdForm(Form):
my_choices = [('1', _('VEHICLES')), ('2', _('Cars')), ('3', _('Motorcycles'))]
nouser = HiddenField(_('No user'))
name = TextField(_('Name'), [validators.Required(message=_('Name is required'))], widget=MyTextInput())
title = TextField(_('Subject'), [validators.Required(message=_('Subject is required'))], widget=MyTextInput())
text = TextAreaField(_('Text'),[validators.Required(message=_('Text is required'))], widget=MyTextArea())
phonenumber = TextField(_('Phone number'))
phoneview = BooleanField(_('Display phone number on site'))
price = TextField(_('Price'),[validators.Regexp('\d', message=_('This is not an integer number, please see the example and try again')),validators.Optional()] )
password = PasswordField(_('Password'),validators=[RequiredIf('nouser', message=_('Password is required'))], widget=MyPasswordInput())
email = TextField(_('Email'), [validators.Required(message=_('Email is required')), validators.Email(message=_('Your email is invalid'))], widget=MyTextInput())
category = SelectFieldWithDisable(choices = my_choices)
def validate_name(form, field):
if len(field.data) > 50:
raise ValidationError(_('Name must be less than 50 characters'))
def validate_email(form, field):
if len(field.data) > 60:
raise ValidationError(_('Email must be less than 60 characters'))
def validate_price(form, field):
if len(field.data) > 8:
raise ValidationError(_('Price must be less than 9 integers'))
Je suppose que je dois définir le 'disabled' attribut quelque part, mais où?
Mise à jour 2
C'était plus compliqué que je ne le pensais. Il y avait aussi un la solution proposé sur le wtforms liste de diffusion mais je ne pouvais pas obtenir que le travail soit (certains banale erreur de syntaxe non valide et ne pas être en mesure d'importer ecscape de wtforms donc l'action que j'ai pris est de mettre à jour mon wtforms de l'hg référentiel si quelque chose d'important changement.
De la réponse ici je obtenir Need more than 2 values to unpack
ou ValueError: too many values to unpack
donc je canät semblent obtenir de droit. Dans mon modèle de ce que je suis en train de rendu est
{{ form.category }}
et ma classe de formulaire est
class AdForm(Form):
my_choices = [('1', _('VEHICLES'), False, True), ('2', _('Cars'), False, False), ('3', _('Motorcycles'), False, False)]
...
category = SelectFieldWithDisable(choices = my_choices)
avec l'ajout de classes que j'ai obtenu à partir d'ici:
class SelectWithDisable(object):
"""
Renders a select field.
If `multiple` is True, then the `size` property should be specified on
rendering to make the field useful.
The field must provide an `iter_choices()` method which the widget will
call on rendering; this method must yield tuples of
`(value, label, selected, disabled)`.
"""
def __init__(self, multiple=False):
self.multiple = multiple
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = 'multiple'
html = [u'<select %s>' % html_params(name=field.name, **kwargs)]
for val, label, selected, disabled in field.iter_choices():
html.append(self.render_option(val, label, selected, disabled))
html.append(u'</select>')
return HTMLString(u''.join(html))
@classmethod
def render_option(cls, value, label, selected, disabled):
options = {'value': value}
if selected:
options['selected'] = u'selected'
if disabled:
options['disabled'] = u'disabled'
return HTMLString(u'<option %s>%s</option>' % (html_params(**options), escape(unicode(label))))
class SelectFieldWithDisable(SelectField):
widget = SelectWithDisable()
def iter_choices(self):
for value, label, selected, disabled in self.choices:
yield (value, label, selected, disabled, self.coerce(value) == self.data)
ad_form = AdForm()
et puis dans votre sortie HTML, il suffit d'imprimer la valeur de "ad_form.catégorie" et "ad_form.nom de l'" et il va retourner le sous-jacent widget html de votre champ sélectionné.(Ran out of room), mais voici un exemple d'utilisation de Jinja:
{{ data.form.time(id="time", value=data.date.strftime("%H:%M"))}}
. le temps est un Champ de texte dans la forme, cela renvoie <input type="text" id="time" name="time" value="[current time formatted as HH:MM]">
Vous pouvez également obtenir une étiquette pour votre domaine avec {{ data.form.time.label }}
qui sera de retour <label for="time'>Time</label>
Le code ci-dessous est attendu recevrez un quatre élément d'un tuple: (valeur, nom, activée (True/False), désactivé (True/False))
Cet être vraiment vieux, je doute que je vais obtenir beaucoup d'aide, mais il serait bien de poster ce que vous avez fait qui a obtenu ce travail. Je suis coincé là où vous étiez.
Cheers, en fin de compte je n'ai trouver comment obtenir le code que vous étiez en train de travailler. Je vais essayer de poster un commentaire quand je suis à mon bureau à ce que j'avais besoin de changer.
OriginalL'auteur Niklas Rosencrantz | 2011-12-11
Vous devez vous connecter pour publier un commentaire.
EDIT:
Si vous voulez toujours de rendre le champ avec certaines options désactivées, vous devrez créer votre propre widget personnalisé et un champ pour fournir au moteur de rendu.
L'actuel moteur de rendu ne prend que trois options de choix du n-uplet:
(value, name, selected)
.Vous aurez besoin de modifier que d'accepter un quatrième élément facultatif: désactivé.
Basée sur la sélection de la classe dans wtforms.widget:
Et puis, sur la base du code de wtforms.champs, sous-classe de la SelectField qui existe déjà
REMARQUE: CE N'EST PAS TESTÉ, NI MÊME D'EXÉCUTER DU CODE PYTHON, MAIS TRÈS RAPIDE HACK COMPTE TENU DE LA QUESTION ET LE CODE SOUS-JACENT DE WTFORMS. Mais il devrait vous donner assez d'une longueur d'avance avec la réponse précédente de contrôler le champ entièrement.
Utilisation de CSS et de JavaScript pour contrôler le rendu de l'élément sur la page.
En quel que soit le modèle de système de rendu de votre aide (je suis en utilisant le flacon, jinja et wtforms) vous rendre votre elemen et de fournir un id ou une classe d'attribut lorsque vous le rendre. (Je suis juste l'impression de
form.select_field_variable_name
)Ensuite générer un fichier CSS pour contrôler votre style et de l'utilisation de JavaScript pour le contrôle personnalisé de la désactivation de certains éléments, etc.
EDIT:
Si vous avez:
Vous pouvez appliquer une couleur d'arrière-plan avec:
Et vous activer/désactiver avec:
Etc, etc, etc.
Une fois que vous avez votre élément rendus à l'aide de WTForms widgets, comme tous les éléments HTML, vous devriez style et de contrôle de toutes les parties dynamiques de l'élément avec CSS et JavaScript
Je vous ai donné de deux façons: l'une pour remplacer le champ et le widget en python par sous-classement dans un nouveau domaine, qui permet de désactivé à être ajouté à la n-uplet utilisé pour le choix et puis des exemples sur comment vous pouvez contrôler l'affichage du widget dans le CSS ainsi que de la façon de désactiver les éléments à l'aide de javascript à la place.
Merci pour la réponse utile. Il a l'air très intéressant et quelque chose que je dois essayer à la fois.
excellemt! ça ne me dérange pas accepter si cela fonctionne pour vous aussi 🙂
J'ai accepté la réponse. Je vous remercie pour votre aide.
OriginalL'auteur tkone
De temps après le fait, je suis allé dans et compris comment faire de la wtform partie de @tkone la réponse de travailler. Je vais ajouter une réponse à cela, car elle ne rentre pas dans un commentaire. En outre, j'ai essayé de le faire avec un
SelectMultipleField
donc, mon domaine est la classe héritant de ce que, au lieu deSelectField
Premier de la classe widget:
Le seul changement d'importer ici, c'est que j'ai
from wtforms import widgets
en haut de mon forms.py si je me réfère à des widgets à l'aide dewidgets.HTMLString
, etc. J'ai également ajouté une taille argument ici, qui serait peut-être mieux être mises en œuvre ailleurs, que définit la taille de l'élément, le nombre d'éléments ou 15, selon le moins élevé. J'ai coincé qu'à l'intérieur de l'auto.plusieurs pour me rappeler d'aller revoir la taille de la chose, si je commence à utiliser ce widget dans d'autres façons.Maintenant le champ de la classe:
C'est là que tous les changements importants ont été apportés. D'abord, comme mentionné précédemment, le champ est d'hériter de la SelectMultipleField classe, j'ai donc ajouter les multiples=Vrai argument pour le widget déclaration. Enfin, je supprime le dernier élément de la iter_choices méthode (
self.coerce(value) == self.data
). Je ne suis pas vraiment sûr de ce qu'il était censé faire, mais dans mon cas elle est toujours par rapport à un entier dans une liste et retourné False, et a abouti à laet
erreur OP était de voir. Si il est de retour quelque chose de précieux, il suffit d'ajouter que variable supplémentaire à la déclaration dans le appel méthode de la classe widget.
Puis quand je suis définir les choix que j'ai juste besoin de mettre le choix tuple pour chaque élément à
(value, label, selected, disabled)
où sélectionné et les personnes handicapées sont les valeurs boolean indiquant si l'élément doit être sélectionné et handicapées, respectivement.J'espère que ça aide quelqu'un comme perdu comme je l'ai été à un certain point bas de la ligne.
OriginalL'auteur UltraBob