2011-12-11 33 views
18

Xác thực biểu mẫu của tôi đang hoạt động gần như hoàn tất, tôi chỉ có 2 trường hợp tôi không biết chính xác cách giải quyết: 1) Trường mật khẩu phải được yêu cầu nhưng tôi cũng cung cấp khả năng đăng nhập bằng tài khoản google hoặc facebook qua OAuth và sau đó tên được điền sẵn nhưng tôi loại bỏ các trường mật khẩu hoàn toàn từ hình thức là có một người dùng (google) hoặc một đối tượng sử dụng facebook:Làm thế nào để tạo một trường có điều kiện tùy chọn trong WTForms?

<tr><td> 
    <br />  {% if user or current_user %} {% else %} 

    <div class="labelform"> 
    {% filter capitalize %}{% trans %}password{% endtrans %}{% endfilter %}: 
    </div> 
     </td><td> <div class="adinput">{{ form.password|safe }}{% trans %}Choose a password{% endtrans %}</div>{% endif %} 

    </td></tr> 

vì vậy, đối với những người dùng đã đăng nhập và trường mật khẩu không có ý nghĩa, tôi cần một số logic để làm cho trường đó có điều kiện tùy ý. Tôi đã nghĩ rằng tôi có thể có một biến cho phương thức logged_in + trong lớp biểu mẫu của tôi như sau:

class AdForm(Form): 
    logged_in = False 
    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')) 

    def validate_password(form, field): 
     if not logged_in and not field: 
      raise ValidationError(_('Password is required')) 

Liệu công cụ validate_password trên đây có đạt được hiệu quả mong muốn không? Có cách nào tốt hơn không? Một cách khác để tôi có thể nghĩ là phải có 2 lớp hình thức khác nhau và trong bài http tôi instanciate lớp hình thức nó nên là:

def post(self): 
    if not current_user: 
     form = AdForm(self.request.params) 
    if current_user: 
     form = AdUserForm(self.request.params) 

Tôi cũng cần xác nhận điều kiện cho lĩnh vực thể loại, khi một thể loại nhất định được chọn sau đó thêm các lựa chọn xuất hiện và những điều này chỉ nên có xác thực cho một danh mục cơ sở nhất định. người dùng chọn "Xe hơi" và sau đó thông qua Ajax có thể chọn dữ liệu đăng ký và số dặm cho ô tô và các trường này được yêu cầu cho rằng danh mục Ô tô đã được chọn.

Vì vậy, có thể có hai câu hỏi nhưng cả hai trường hợp đều liên quan đến cách tôi có thể tạo trường "có điều kiện tùy chọn" hoặc "có điều kiện bắt buộc".

dạng của tôi trông như thế này

enter image description here

Và đối với một đăng nhập người sử dụng tôi điền trước tên và địa chỉ email và các lĩnh vực pasword chỉ đơn giản là không được sử dụng, vì vậy trường mật khẩu không phù hợp là "bắt buộc" cũng không phải "bắt buộc", nó sẽ cần một cái gì đó như "có điều kiện tùy chọn" hoặc "có điều kiện bắt buộc".

enter image description here

Thanks cho bất kỳ câu trả lời hoặc bình luận

Trả lời

53

Tôi không chắc chắn này khá phù hợp với nhu cầu của bạn, nhưng tôi đã sử dụng một validator RequiredIf tùy chỉnh trên các lĩnh vực trước đây, mà làm cho một trường bắt buộc nếu một trường có một giá trị trong biểu mẫu ... ví dụ, trong một kịch bản múi giờ và múi giờ, tôi có thể làm cho trường múi giờ bắt buộc phải có một giá trị nếu người dùng đã nhập một ngày giờ.

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 bool(other_field.data): 
      super(RequiredIf, self).__call__(form, field) 

Các nhà xây dựng có tên của các lĩnh vực khác mà gây nên làm cần lĩnh vực này, như:

class DateTimeForm(Form): 
    datetime = TextField() 
    timezone = SelectField(choices=..., validators=[RequiredIf('datetime')]) 

Đây có thể là điểm khởi đầu tốt cho việc thực hiện các loại logic bạn cần.

+2

Giấy phép sử dụng đoạn mã của bạn là gì? –

+1

@Mehdi: http://meta.stackexchange.com/questions/12527/do-i-have-to-worry-about-copyright-issues-for-code-posted-on-stack-overflow – brandones

+0

Awesome³! Hoạt động thực sự tốt! – Roman

4

Tôi thấy câu hỏi này hữu ích và dựa trên câu trả lời của @dcrosta tôi đã tạo một trình xác thực khác là tùy chọn. Lợi ích là bạn có thể kết hợp nó với các trình xác nhận hợp lệ khác. Đây là trình xác nhận tùy chọn của tôi để kiểm tra một trường khác.Bởi vì tôi cần thiết để kiểm tra giá trị của lĩnh vực khác chống lại một số giá trị nhất định tôi đã thêm một tấm séc tùy chỉnh cho giá trị:

class OptionalIfFieldEqualTo(wtf.validators.Optional): 
    # a validator which makes a field optional if 
    # another field has a desired value 

    def __init__(self, other_field_name, value, *args, **kwargs): 
     self.other_field_name = other_field_name 
     self.value = value 
     super(OptionalIfFieldEqualTo, 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 == self.value: 
      super(OptionalIfFieldEqualTo, self).__call__(form, field) 
2

Câu trả lời từ @dcrosta là rất tốt, nhưng tôi nghĩ rằng một số thứ đã thay đổi trong wtforms kể từ khi câu trả lời này . Kế thừa từ DataRequired thêm thuộc tính required vào trường biểu mẫu, do đó trình xác thực có điều kiện không bao giờ được gọi. Tôi đã thực hiện một thay đổi nhỏ cho lớp học từ @dcrosta hoạt động với wtforms 2.1. Điều này chỉ vượt quá field_flags để xác thực trình duyệt không được thực hiện.

from wtforms.validators import DataRequired 


class RequiredIf(DataRequired): 
    """Validator which makes a field required if another field is set and has a truthy value. 

    Sources: 
     - http://wtforms.simplecodes.com/docs/1.0.1/validators.html 
     - http://stackoverflow.com/questions/8463209/how-to-make-a-field-conditionally-optional-in-wtforms 

    """ 
    field_flags = ('requiredif',) 

    def __init__(self, other_field_name, message=None, *args, **kwargs): 
     self.other_field_name = other_field_name 
     self.message = message 

    def __call__(self, form, field): 
     other_field = form[self.other_field_name] 
     if other_field is None: 
      raise Exception('no field named "%s" in form' % self.other_field_name) 
     if bool(other_field.data): 
      super(RequiredIf, self).__call__(form, field) 

Giải pháp lý tưởng hơn sẽ quản lý xác thực trong trình duyệt, như hành vi hiện tại của DataRequired.

Các vấn đề liên quan