2017-03-23 30 views
1

我想對Flask管理員執行一些驗證。 Flask應用程序連接到後端postgreSQL數據庫並使用SQLAlchemy ORM。如何在Flask管理員字段上執行驗證

我希望能夠在ServerView(flask.ext.admin.contrib.sqla.modelView)中的兩個字段(lan_nics,wan_nics)上執行驗證檢查。基本上我想確保兩個字段的總和不大於某個數字。這裏是形式:

ServerView

這裏是test_app代碼。我試圖按照flask-admin的文檔。我添加了一個def,然後在form_args中爲驗證器字典引用了def ......但它似乎不起作用。目前,我只是想確保這兩個字段有一個值小於5

from flask import Flask 
from flask.ext.admin import Admin 
from flask.ext.admin.contrib.sqla import ModelView 
from flask.ext.sqlalchemy import SQLAlchemy 
from wtforms.validators import ValidationError 
import psycopg2 


# Flask and Flask-SQLAlchemy initialization here 

app = Flask(__name__) 
db = SQLAlchemy(app) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:[email protected]/testdb' 
app.secret_key = 'MySecret' 
conn = psycopg2.connect("dbname='testdb' user='postgres' host='127.0.0.1' password='postgres'") 

class Server(db.Model): 
    __tablename__ = "server" 
    id = db.Column('server_id', db.Integer, primary_key=True) 
    model = db.Column('model', db.Unicode) 
    lan_nics = db.Column('lan_nics', db.Integer) 
    wan_nics = db.Column('wan_nics', db.Integer) 

    def __str__(self): 
     return self.model 

class Hardware(db.Model): 
    __tablename__ = "hardware" 
    id = db.Column('hardware_id', db.Integer, primary_key=True) 
    model = db.Column('model', db.Unicode) 
    max_nics = db.Column('max_nics', db.Integer) 

    def __str__(self): 
     return self.model 


class ServerView(ModelView): 

    # Disable model creation 
    can_create = True 

    # Override displayed fields 
    column_list = ('model', 'lan_nics', 'wan_nics') 

    column_display_all_relations = True 
    column_searchable_list = ('model') 
    column_labels = dict(model='Model', lan_nics='LAN Nics', wan_nics='WAN NICs') 
    form_columns = [ 'model', 'lan_nics', 'wan_nics' ] 


    def max_allowed(form, field): 
     if field.data > 5: 
      raise ValidationError('Max number of interfaces exceeded') 

    form_args = dict(
     lan_nics=dict(validators=[max_allowed]), 
     wan_nics=dict(validators=[max_allowed]) 
    ) 


class HardwareView(ModelView): 
    # Disable model creation 
    can_create = True 

    # Override displayed fields 
    column_list = ('model', 'max_nics') 

    column_display_all_relations = True 
    column_searchable_list = ('model') 
    column_labels = dict(model='Model', max_nics='Max Nics') 
    form_columns = ['model', 'max_nics' ] 

    def __str__(self): 
     return self.model 


admin = Admin(app, name="MyApp1") 
# Add administrative views here 
admin.add_view(ModelView(Server, db.session)) 
admin.add_view(ModelView(Hardware, db.session)) 

app.run(port=8000, host="0.0.0.0") 
+0

form_args'不應該'max_allowed'是'max_allowed()'? – pjcunningham

+0

@pjcunningham不,你需要傳遞函數引用,所以他這樣做的方式是正確的。 – MrLeeh

+0

@Jayjay_Jay你這樣做的方式應該實際上工作。驗證器已正確實施。檢查字段「lan_nics」和「wan_nics」的類型是整型還是浮點型。如果它們是字符串,則需要將它們轉換爲int來完成此工作。 – MrLeeh

回答

1

相反的form_args,我做了on_model_change:在`

class ServerView(ModelView): 
    ... 
    ... 
    ... 

    def on_model_change(self, form, model, is_created): 
     hardware = "hardware" 
     query = "SELECT nics FROM hardware WHERE model = '{}'".format(hardware) 
     with conn.cursor() as cur: 
      cur.execute(query) 
      max_nics = int(cur.fetchone()[0]) 
     if (int(form.lan.data) + int(form.wan.data) > max_nics): 
      raise ValidationError('Max number of interfaces exceeded!') 
     else: 
      return model