python - 如何定位我的wtform?

标签 python google-app-engine jinja2 wtforms babel

我有一个表格,我想把它从英语本地化为多种语言。我可以使用gettext或数据存储来实现,我选择gettext是为了提高性能,但我也可以使用数据存储来存储我的翻译。实际的翻译存储在.po文件中,我使用poedit将其编译为.mo本地化文件。表单的视图是:
验证也会本地化,但应该要求的类别不起作用:
后端代码是

class MyTextInput(TextInput):

    def __init__(self, error_class=u'has_errors'):
        super(MyTextInput, self).__init__()
        self.error_class = error_class

    def __call__(self, field, **kwargs):
        if field.errors:
            c = kwargs.pop('class', '') or kwargs.pop('class_', '')
            kwargs['class'] = u'%s %s' % (self.error_class, c)
        return super(MyTextInput, self).__call__(field, **kwargs)


class MyPasswordInput(PasswordInput):

    def __init__(self, error_class=u'has_errors'):
        super(MyPasswordInput, self).__init__()
        self.error_class = error_class

    def __call__(self, field, **kwargs):
        if field.errors:
            c = kwargs.pop('class', '') or kwargs.pop('class_', '')
            kwargs['class'] = u'%s %s' % (self.error_class, c)
        return super(MyPasswordInput, self).__call__(field, **kwargs)


class RequiredIf(Required):

    # a validator which makes a field required if
    # another field is set and has a truthy value

    def __init__(
        self,
        other_field_name,
        *args,
        **kwargs
        ):

        self.other_field_name = other_field_name
        super(RequiredIf, self).__init__(*args, **kwargs)

    def __call__(self, form, field):
        other_field = form._fields.get(self.other_field_name)
        if other_field is None:
            raise Exception('no field named "%s" in form'
                            % self.other_field_name)
        if other_field.data:
            logging.info('other_field.data 2' + str(other_field.data))
            super(RequiredIf, self).__call__(form, field)


class MyTextArea(TextArea):

    def __init__(self, error_class=u'has_errors'):
        super(MyTextArea, self).__init__()
        self.error_class = error_class

    def __call__(self, field, **kwargs):
        if field.errors:
            c = kwargs.pop('class', '') or kwargs.pop('class_', '')
            kwargs['class'] = u'%s %s' % (self.error_class, c)
        return super(MyTextArea, self).__call__(field, **kwargs)


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)


from wtforms.widgets import html_params, HTMLString
from cgi import escape


class MyOption(object):

    def __call__(self, field, **kwargs):
        options = dict(kwargs, value=field._value())
        if field.checked:
            options['selected'] = True

        label = field.label.text
        render_params = (html_params(**options), escape(unicode(label)))
        return HTMLString(u'<option %s>%s</option>' % render_params)


class AdForm(Form):

    my_choices = [
        ('1', _('All categories')),
        ('disabled', _('VEHICLES')),
        ('2', _('Cars')),
        ('3', _('Motorcycles')),
        ('4', _('Accessories & Parts')),
        ('disabled', _('PROPERTIES')),
        ('7', _('Apartments')),
        ('8', _('Houses')),
        ('9', _('Commercial properties')),
        ('10', _('Land')),
        ('disabled', _('ELECTRONICS')),
        ('12', _('Mobile phones & Gadgets')),
        ('13', _('TV/Audio/Video/Cameras')),
        ('14', _('Computers')),
        ('disabled', _('HOME & PERSONAL ITEMS')),
        ('16', _('Home & Garden')),
        ('17', _('Clothes/Watches/Accessories')),
        ('18', _('For Children')),
        ('disabled', _('LEISURE/SPORTS/HOBBIES')),
        ('20', _('Sports & Outdoors')),
        ('21', _('Hobby & Collectables')),
        ('22', _('Music/Movies/Books')),
        ('23', _('Pets')),
        ('20', _('BUSINESS TO BUSINESS')),
        ('24', _('Hobby & Collectables')),
        ('25', _('Professional/Office equipment')),
        ('26', _('Business for sale')),
        ('disabled', _('JOBS & SERVICES')),
        ('28', _('Jobs')),
        ('29', _('Services')),
        ('30', _('Events & Catering')),
        ('31', _('Others')),
        ]
    nouser = HiddenField(_('No user')) #dummy variable to know whether user is logged in
    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'), [validators.Optional()])
    phoneview = BooleanField(_('Display phone number on site'))
    price = TextField(_('Price'), [validators.Regexp('^[0-9]+$',
                      message=_('This is not an integer number, please see the example and try again'
                      )), validators.Optional()], widget=MyTextInput())
    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 = SelectField(choices=my_choices, option_widget=MyOption())

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

相关模板代码为:
<div class="labelform">
    <label>
{% trans %}Category{% endtrans %}:
</label>
  </div></td><td>
  <div class="adinput">

   <select name="{{ form.category.name }}">
   {% for option in form.category %}
       {% if option.data == 'disabled' %}
           {{ option(disabled=True) }}
       {% else %}
           {{ option }}
       {% endif %}
   {% endfor %}
   </select>

    <div id="err_category" style="display: none; color: red; font-weight: bold;">
      <span class="error" id="err_msg_category"></span>
    </div>
  </div>
  </td></tr><tr><td>
    <div class="labelform"></div></td><td>
    <div class="adinput">
        <label for="private_ad" id='lprivate_ad'>
        <input id="private_ad" name="company_ad" value="0" checked="checked" type="radio" />
{% trans %}Private{% endtrans %}    
        </label>
    <label for="company_ad" id='lcompany_ad'>
        <input id="company_ad" name="company_ad" value="1" type="radio" />      
{% trans %}Company{% endtrans %}
    </label>
    </div>
    </td></tr><tr><td valign="top">
    {{ form.name.label }}:</td><td>
  <div class="adinput">
{% if user or current_user %} 
    <input type="text" id="name" name="name" value="{{ current_user.name }}{% if not current_user %}{{ user.nickname() }}{% endif %}" size="35" maxlength="50" readonly/>
  {% else %}
    {{ form.name|safe }}
{% endif %}
{% if form.name.errors %} <div class="red">
        <ul class="errors">{% for error in form.name.errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
    {% endif %}
  </div>
  </td></tr><tr><td valign="top">
{{ form.email.label }}:</td><td>
  <div class="adinput">
{% if user.email or current_user.email %} 
<input type="text" id="email" name="email" value="{{ current_user.email }}{% if not current_user %}{{ user.email() }}{% endif %}" size="35" maxlength="60" readonly /> 
  {% else %}
    {{ form.email|safe }}
{% endif %}{% if form.email.errors %} <div class="maintext">
        <ul class="errors">{% for error in form.email.errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
    {% endif %}
  </div>
  </td></tr><tr><td valign="top">{% if not user and not current_user %}
{{ form.password.label }}:
      </td><td>  <div class="adinput">{{ form.password|safe }}{% trans %}Choose a password{% endtrans %}</div>{% if form.password.errors %} <div class="maintext">
        <ul class="errors">{% for error in form.password.errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
    {% endif %}{% endif %}

  </td></tr><tr><td valign="top">
    {{ form.phonenumber.label }}:
  </td><td valign="top">
  <div class="adinput">
    {{ form.phonenumber(size="17", maxlength="14")|safe }}{% trans %}Use areacode{% endtrans %}<br>
    {{ form.phoneview|safe }}
    <label for="phone_hidden">{% trans %}View on site{% endtrans %}</label><br />
    {{mareacode}}.
    <div id="err_phone" style="display: none;">
      <span class="warning" id="err_msg_phone"></span>
    </div>
  </div></td></tr><tr><td valign="top">
    <div class="labelform">
 {% filter capitalize %}{% trans %}content type{% endtrans %}{% endfilter %}:</div></td><td>
    <div class="adinput" id="dtype">
    <label style="cursor:pointer;" for="type_s" id="ltype_s">
        <input type="radio" name="type" id="type_s" value="s" checked="checked"  />
 {% trans %}For sale{% endtrans %}
    </label>
      <label style="cursor:pointer;" for="type_k" id="ltype_k">
        <input type="radio" name="type" id="type_w" value="w" />{% trans %}Wanted{% endtrans %}
    </label>
            <div id="warn_type" style="display: none;">
                <span class="warning" id="err_msg_type"></span>
            </div>
      </div>
</td></tr>



<!--
<tr>
<th style="display: table-cell;">Reg. Year:</th>
<td class="param_cell_regdate" style="display: table-cell;">
<select id="regdate" name="regdate">
<div id="err_regdate" style="display: none">
<div class="warning" style="display:none; clear:both; float:none; white-space:nowrap"> </div>
</td>
</tr>
-->


<tr><td valign="top">
{{ form.title.label }}:
  </td><td>
{{ form.title(size='47', maxlength='50', placeholder=_('Please use a descriptive title'))}}{% if form.title.errors %}
        <div class="maintext"> <ul class="errors">{% for error in form.title.errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
    {% endif %}
    <br/>
    </td></tr><tr><td valign="top">
{{ form.text.label }}:
  </td><td colspan="2">
  <div class="adinput">
   {{form.text(cols="45", rows="10", placeholder=_('Please describe the product or service in a few simple sentences'))|safe}}
{% if form.text.errors %} <div class="maintext">
        <ul class="errors">{% for error in form.text.errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
    {% endif %}
  </div></td></tr><tr><td>
{{ form.price.label }}:
      </td><td>
      <div class="adinput" id="dprice" style="display: block;">{% if host == "www.montao.com.br" %}R${% else %}
</label><select name="currency" class="currencySelect">
<option value="EUR" >Euros</option>
<option value="AUD">{% trans %}Australian{% endtrans %} Dollars</option>
<option value="BRL" {% if logo == "Montao.com.br" %}selected{% endif %}>{% trans %}Brazilian{% endtrans %} Real</option>
<option value="GBP">{% trans %}British{% endtrans %} Pounds</option>
<option value="CAD">{% trans %}Canadian{% endtrans %} Dollars</option>
<option value="CZK">{% trans %}Czech{% endtrans %} Koruny</option>
<option value="DKK">{% trans %}Danish{% endtrans %} Kroner</option>
<option value="HKD">{% trans %}Hong Kong{% endtrans %} Dollars</option>
<option value="HUF">{% trans %}Hungarian{% endtrans %} Forints</option>
<option value="INR">{% trans %}Indian{% endtrans %} Rupee</option>
<option value="ILS">{% trans %}Israeli{% endtrans %} New Shekels</option>
<option value="JPY">{% trans %}Japanese{% endtrans %} Yen</option>
<option value="MXN">{% trans %}Mexican{% endtrans %} Pesos</option>
<option value="NZD">{% trans %}New Zealand{% endtrans %} Dollars</option>
<option value="NOK">{% trans %}Norwegian{% endtrans %} Kroner</option>
<option value="PHP">{% trans %}Philippine{% endtrans %} Pesos</option>
<option value="PLN">{% trans %}Polish{% endtrans %} Zlotych</option>
<option value="SGD">{% trans %}Singapore{% endtrans %} Dollars</option>
<option value="SEK">{% trans %}Swedish{% endtrans %} Kronor</option>
<option value="CHF">{% trans %}Swiss{% endtrans %} Francs</option>
<option value="TWD">{% trans %}Taiwan{% endtrans %} New Dollars</option>
<option value="THB">{% trans %}Thai{% endtrans %} Baht</option>
<option value="USD">U.S. Dollars</option>
</select>{% endif %}{{ form.price|safe }}{% if logo == "Montao.com.br" %},{% else %}.{% endif %}00 ({% trans %}Optional - do not include period, comma or cents{% endtrans %})
{% if form.price.errors %}
        <ul class="errors">{% for error in form.price.errors %}<li>{{ error }}</li>{% endfor %}</ul>
    {% endif %}
    </div>
  </td></tr><tr><td>
<div class="labelform">
    <label>{% trans %}Post a photo{% endtrans %}</label>
  </div></td><td>
  <div class="adinput">
    <input type="file" multiple="true" name="file[]" size="35" id="file" />({% filter capitalize %}{% trans %}optional{% endtrans %}{% endfilter %}. {% trans %}Use CTRL on your keyboard to select multiple images.{% endtrans %}) {{resize}}
  </div>
  </td></tr><tr><td></td><td><div class="labelform"></div><div class="adinput">
<!--
{% if not isHuman %} 
{% trans %}You missed the anti-spam test! No problem, please try again:{% endtrans %}
{% endif %}
{{capture|safe}}
-->
<input type="submit" name="validate" value='{% trans %}Continue{% endtrans %}' /></div></td></tr></table></form>

我接收表单输入的方式是使用http post:
        form = AdForm(self.request.params)
        if form.validate():
            ad.title = form.title.data
            ad.name = form.name.data
            ad.email = form.email.data
            ad.phoneview = form.phoneview.data
            try:
                if form.phonenumber.data:
                    ad.phonenumber = form.phonenumber.data
            except:# to do: change to finally
                pass

            ad.text = form.text.data
            ad.set_password(form.password.data)
            ad.price = form.price.data.replace(' ', '').replace(',00',
                    '').replace('.00', '')
            try:
                if form.price.data:
                    ad.integer_price = form.price.data.replace(' ', ''
                            ).replace(',00', '').replace('.00', '')
            except:
                pass
            ad.url = self.request.host
            ad.place = self.request.get('place')
            ad.postaladress = self.request.get('place')
            ad.put()
        else:
            logging.info('form did not validate')
            self.render_jinja('insert_jinja',
                              facebook_app_id=facebookconf.FACEBOOK_APP_ID,
                              form=form,
                              form_url=blobstore.create_upload_url('/upload_form'
                              ))
            return
        if self.request.get('currency'):
            ad.currency = self.request.get('currency')
        if self.request.get('cg'):
            ad.category = self.request.get('cg')  # form.cg.data
        if self.request.get('company_ad') == '1':
            ad.company_ad = True
        ad.put()

        if self.request.host.find('montao') > 0 \
            or self.request.host.find('localhost') > 0:
            path = os.path.join(os.path.dirname(__file__), 'market',
                                'market_ad_preview.html')
            ad.url = self.request.host

        for upload in self.get_uploads():
            try:
                img = Image(reference=ad)
                img.primary_image = upload.key()
                img.put()
                ad.put()
            except: # to do: change to finally
                pass
        ad.put()
        msg = _('Added %s.') % str(self.request.get('title'))
        message = mail.EmailMessage(sender=self.current_email,
                                    subject=(ad.title if ad.title else ''
                                    ))
        if self.request.host != 'www.montao.com.br':
            message.body = 'Dear ' + ad.name \
                + '\nThank you for registering with ' \
                + self.request.host \
                + '! To edit your ad, click edit from the menu. ' \
                + self.request.host + '/vi/' + str(ad.key().id()) \
                + '''.html
We invite you to visit our home page where you can find latest information on new business announcements from us. From there you can also upload and download videos, music and images.
If you like, you can also add us on Facebook: apps.facebook.com/koolbusiness'''
            message.to = ad.email
            message.send()
        self.redirect('/vi/%d.html' % (ad.key().id(), ))

为什么我的分类不翻译?当选项也应该能够禁用并且在这些情况下获得灰色背景时,处理我的类别的最佳方法是什么?你能看到更多的方法把渲染从硬编码的html和模板代码转移到wtforms吗?
如有任何回答或意见,请提前表示感谢。

最佳答案

在选项定义中必须使用某种Lazy gettext

关于python - 如何定位我的wtform?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8786498/

相关文章:

python - 如何在 jinja2 过滤器中使用嵌套 if

python - 提交作业,等待其完成,然后提交另一个作业

python - 列表元素索引的输出不正确 - Python

python - '类型错误 : an integer is required' when initializing random weight matrix in numpy with numpy. random.randn()

python - 如何在 Google App Engine 中对来自 webapp WSGI 应用程序的响应进行单元测试?

python - 在不知道 'compile' 时间的属性名称的情况下,在 Python 中复制 Google App Engine 数据存储中的实体

java - Google App 引擎 + Spring = 启动慢?

python - 在 Jinja2 中迭代列表的列表,断言多个条件并在 true 时渲染

python - 使用应用工厂的 Flask 应用找不到模板

python - 在Python中,尝试将整数转换为字符并放入二进制 "string"