Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
332 views
in Technique[技术] by (71.8m points)

python - Flask: conditional validation on multiple form fields

Let me start with usual - I'm new to both Python & Flask. Before posting this question (my first ever here) I have spent number of hours searching and experimenting, unfortunately with no luck so far.

I am building web form where user can define firewall rules, which subsequently get recorded in the database. I am at the validation stage and I came up to a wall here... hopefully someone will be able to help me out.

My (simplified here) form has 2 fields - src_ip and dst_ip:

class FirewallRule(Form)
    src_ip = StringField('Source IP')
    dst_ip = StringField('Destination IP')

and my validation requirements are:

  1. At least 1 field must be filled (both are also fine)
  2. Fields that are filled must contain valid IP address

wtforms.validators.IPAddress() and custom validation function seems to be my friend, but I am struggling to find a way to plug them together.

Essentially I am trying to build conditional validation:

  1. If not (src_ip OR dst_ip); return False
  2. If src_ip AND src_ip not valid IP address; return False
  3. If dst_ip AND dst_ip not valid IP address; return False
  4. Return True

Obviously I would like to re-use IPAddress() [or generally any of the built-in validators] rather then write my own.

I am sure someone must have done it before.. unfortunately I could not find any pointers in the right direction.

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are missing one very useful validator: Optional. This validator allows you to say that a field can be empty, but if it isn't empty then other validators should be used.

The part about having at least one of the fields filled out I would do with a custom validation method, I don't think there is any stock validators that can help with that.

So it would be something like this:

class FirewallRule(Form)
    src_ip = StringField('Source IP', validators=[Optional(), IPAddress()])
    dst_ip = StringField('Destination IP', validators=[Optional(), IPAddress()])

    def validate(self):
        if not super(FirewallRule, self).validate():
            return False
        if not self.src_ip.data and not self.dst_ip.data:
            msg = 'At least one of Source and Destination IP must be set'
            self.src_ip.errors.append(msg)
            self.dst_ip.errors.append(msg)
            return False
        return True

If you want to avoid a custom validation function, then consider that it would be fairly easy to create a validator class to check that at least one of a list of fields are set. You can look at the implementation of the EqualTo validator for inspiration if you would like to follow this route.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...