简体   繁体   中英

How to perform Validation on Flask-admin fields

I want to perform some validation on Flask Admin. The Flask app is connected to a backend postgreSQL DB and is using SQLAlchemy ORM.

I want to be able to perform validation checks on two fields (lan_nics, wan_nics) in the ServerView(flask.ext.admin.contrib.sqla.modelView). Basically I want to ensure the sum of two fields are not greater than a certain number. Here is the form:

ServerView

Here is the test_app code. I've tried to follow the documentation for flask-admin. I added a def and then referenced that def in the form_args for validators dictionary... but it doesn't seem to work. At the moment I'm just trying to ensure that both of the fields have a value less than 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:postgres@127.0.0.1/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")

Instead of form_args , I did 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

Actually, your first approach works. You have a small typo: instead of if field.data > 5: you should check for if len(field.data) > 5: .

The documentation of flask-admin does not really cover validators but under the hood, it does just delegate the work to WTForms. Their documentation is very helpful: https://wtforms.readthedocs.io/en/3.0.x/validators/ It also shows existing validators such as Length , you could have written instead:

from wtforms.validators import Length

form_args = dict(
    lan_nics=dict(
        validators=[Length(min=5, message='Max number of interfaces exceeded')]
    ), 
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM