2015-08-18 24 views
4

我正在從iOS應用程序接收用戶註冊數據,我想使用wtforms附帶的驗證程序來確保電子郵件和密碼是可接受的。但是,我沒有使用燒瓶形式,因爲用戶從iOS文本框輸入數據。是否可以使用wtforms驗證器檢查傳入的JSON數據?使用flask wtforms驗證程序而不使用表單

@auth.route('/register', methods=['POST']) 
def register(): 
    try: 
     user = User.register_fromJSON(request.json) 

     email_success = validate_email(user) 
     username_success = validate_username(user) 

     if email_success == 1 and username_success == 1: 
      db.session.add(user) 
      db.session.commit() 
      return jsonify({'Success': 1}) 
     else: 
      return jsonify({'Failure': 0}) 

    except Exception: 
     return jsonify({'Failure': 0}) 

def validate_email(user): 
    if User.query.filter_by(email=user.email).first() == None: 
     return 1 
    else: 
     return 0 

def validate_username(user): 
    if User.query.filter_by(username=user.username).first() == None: 
     return 1 
    else: 
     return 0 

EDIT

我創建了一個登記表:

class RegistrationForm(Form): 
    email = StringField('Email', validators=[Required(), Length(1,64), Email()]) 
    username = StringField('Username', validators=[Required(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0, 'Usernames must have only letters, 'numbers, dots or underscores')]) 
    password = PasswordField('Password', validators=[Required()]) 


    def validate_email(self, field): 
     if User.query.filter_by(email=field.data).first(): 
      print("Email already registered.") 
      raise ValidationError('Email already registered.') 

    def validate_username(self, field): 
     if User.query.filter_by(username=field.data).first(): 
      print("Username already in use.") 
      raise ValidationError('Username already in use.') 

登記功能已經被更新爲:

@auth.route('/register', methods=['POST']) 
def register(): 
    try: 
     data = MultiDict(mapping=request.json) 
     form = RegistrationForm(data) 

     if form.validate(): 
      user = User.register_fromJSON(request.json) 
      db.session.add(user) 
      db.session.commit() 
      return jsonify({'Success': 1}) 
     else: 
      return jsonify({'Success': 2}) 

    except Exception: 
     return jsonify({'Success': 3}) 
+0

絕對。我實際上正在編寫一個完全符合這個要求的庫。在我的手機上,但是當我回到鍵盤上時我會發佈一個答案 – nathancahill

回答

7

是的,這是完全可能的 - 的wtforms.Form構造函數採用任何MultiDict喜歡的界面(it just needs to have getlist),所以你可以從你的JSON創建werkzeug.datastructures.MultiDict一個實例:

data = MultiDict(mapping=request.json) 
form = YourForm(data) 
if form.validate(): 
    # Data is correct 

(假設字段名匹配),而事情會只是工作

+0

那麼你是否實際上製作了一個假的表單,JSON數據被分配到了然後被驗證? – Brosef

+0

是的,有效。我正在使用Flask/Werkzeug用於'request.form'的底層數據結構從'request.json'解析的字典中構建一個類似字典的對象,所以WTForms對它進行處理。 WTForms不關心數據是從HTML表單POST還是從INI文件中解析出來的 - 它只需要在一個像MultiDict一樣的數據結構中提供。 –

+0

我似乎無法獲得驗證的表單。我錯過了什麼嗎?我可以通過執行form.email.data來打印表單數據,並且它都是正確的。 – Brosef

1

這是一個叫做Flask-Inputs的小工具,我正在努力解決這個問題。目標是允許所有傳入的數據(表單,查詢,頭文件等)通過wtform驗證器進行驗證。

這裏是如何驗證會與您的數據的工作:

from flask_inputs import Inputs 
from wtforms.validators import Length, Email, ValidationError 


class RegisterInputs(Inputs): 
    json = { 
     'email': [Email(), unique_email], 
     'username': [Length(min=3, max=15), unique_username] 
    } 

def unique_email(form, field): 
    if User.query.filter_by(email=field.data).first(): 
     raise ValidationError('Email is already registered.') 

def unique_username(form, field): 
    if User.query.filter_by(username=field.data).first(): 
     raise ValidationError('Username is already registered.') 


@auth.route('/register', methods=['POST']) 
def register(): 
    inputs = RegisterInputs(request) 

    if inputs.validate(): 
     user = User.register_fromJSON(request.json) 

     db.session.add(user) 
     db.session.commit() 

     return jsonify(success=1) 
    else: 
     return jsonify(failure=0, errors=inputs.errors) 
+0

因此在'register()'下,請求被作爲參數發送到'RegisterInputs()'。現在,「輸入」只是一個包含電子郵件和用戶名的鍵和值的字典嗎?這不是在數據從JSON轉換之前發生的,因爲一切都發生在'user = User.register_fromJSON(request.json)'之前? – Brosef

+0

輸入就像wtforms中的一個表單實例。你可以調用inputs.validate()來檢查json是否有效 – nathancahill

+0

對不起,如果我是nitpicky,但我認爲JSON數據需要首先解析,然後輸入到表單實例。我的邏輯錯了嗎?您的答案看起來像表單實例正在填充直JSON數據。 – Brosef