Flask WTForms - Custom validators based of multiple form fields

Stevan Stankovic

I have a books table where quantity of books is available and I have borrows table where I enter the borrowed books and quantities.

I am trying to create custom validator function for my form that will show error message in form if quantity entered for borrow book is higher than available quantity in book table.

this is the model:

class Borrow(db.Model):
    """
    Create a Books table
    """

    __tablename__ = 'borrows'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(60), index=True)
    quantity_borrow = db.Column(db.Integer)
    date_borrow = db.Column(db.DATE)
    employees_id = db.Column(db.Integer, db.ForeignKey('employees.id'))
    book_id = db.Column(db.Integer, db.ForeignKey('books.id'))

    def __repr__(self):
        return '<Borrow: {}>'.format(self.name)


class Book(db.Model):
    """
    Create a Books table
    """

    __tablename__ = 'books'

    id = db.Column(db.Integer, primary_key=True)
    book_name = db.Column(db.String(60), index=True,unique=True)
    author = db.Column(db.String(200), index=True)
    quantity = db.Column(db.Integer)
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))
    employees_id = db.Column(db.Integer, db.ForeignKey('employees.id'))
    publisher = db.Column(db.String(200))
    no_of_pgs = db.Column(db.Integer)
    pbs_year = db.Column(db.Integer)
    genre_id = db.Column(db.Integer, db.ForeignKey('genres.id'), nullable=False)
    read = db.Column(db.Enum('NO', 'YES'), default='NO')

    borrows = db.relationship('Borrow', backref='book',
                                lazy='dynamic')

This is the view:

    @admin_role.route('/books/add', methods=['GET', 'POST'])
    @login_required
    def add_book():
        """
        Add a book to the database
        """
        check_admin_role()

        add_book = True

        form = BookForm()
        if form.validate_on_submit():
            book = Book(book_name=form.book_name.data,
                        author=form.author.data,
                        quantity=form.quantity.data,
                        department_id=form.department_name.data,
                        employees_id=current_user.id,
                        publisher=form.publisher.data,
                        no_of_pgs=form.no_of_pgs.data,
                        pbs_year=form.pbs_year.data,
                        genre_id=form.genre_name.data,
                        read=form.read.data)
            try:
                # add department to the database
                db.session.add(book)
                db.session.commit()
                flash('You have successfully added a new department.')
            except:
                # in case department name already exists
                flash('Error: Book name already exists.')

            # redirect to departments page
            return redirect(url_for('admin_role.list_books'))

        # load department template
        return render_template('books/book.html', action="Add",
                               add_book=add_book, form=form,
                               title="Add Book", page="books")


    @admin_role.route('/borrows/add', methods=['GET', 'POST'])
    @login_required
    def add_borrow():
        """
        Add a borrow to the database
        """
        check_admin_role()

        add_borrow = True

        form = BorrowForm()

        if form.validate_on_submit():
            borrow = Borrow(name=form.name.data,
                        book_id=form.book_name.data,
                        quantity_borrow=form.quantity_borrow.data,
                        date_borrow=form.date_borrow.data)

            # add department to the database
            db.session.add(borrow)
            db.session.commit()
            flash('You have successfully added a new borrow.')


            # redirect to borrows page
            return redirect(url_for('admin_role.list_borrows'))

        # load department template
        return render_template('borrows/borrow.html', action="Add",
                               add_borrow=add_borrow, form=form,
                               title="Add Borrow", page="borrows")

And this is the form

class BookForm(FlaskForm):
    """
    Form for admin_role to add or edit a books
    """
    book_name = StringField('Book Name', validators=[DataRequired()])
    author = StringField('Author', validators=[DataRequired()])
    genre_name = SelectField(coerce=int, validators=[DataRequired()])
    quantity = IntegerField('Quantity', validators=[DataRequired()])
    department_name = SelectField(coerce=int, validators=[DataRequired()])
    publisher = StringField('Publisher', validators=[DataRequired()])
    no_of_pgs = IntegerField('Number of pages', validators=[DataRequired()])
    pbs_year = IntegerField('Publishing Year', validators=[DataRequired()])
    read = SelectField("Read", choices=[(e, e) for e in Book.read.property.columns[0].type.enums])
    submit = SubmitField('Submit')

    def __init__(self):
        super(BookForm, self).__init__()
        self.department_name.choices = [(c.id, c.name) for c in Department.query.all()]
        self.genre_name.choices = [(g.id, g.name) for g in Genre.query.all()]


class BorrowForm(FlaskForm):
    """
    Form for admin_role to add or edit a books
    """
    name = StringField('Borrower Name', validators=[DataRequired()])
    book_name = SelectField(coerce=int, validators=[DataRequired()])
    quantity_borrow = IntegerField('Quantity Borrow', validators=[DataRequired())
    date_borrow = DateField('Borrow Date', validators=[DataRequired()])

    submit = SubmitField('Submit')

    def __init__(self):
        super(BorrowForm, self).__init__()
        self.book_name.choices = [(c.id, c.book_name) for c in Book.query.all()]
Berkin Anık

In wtforms you can validate a field by writing a method under that form class.

In this method, validate_ prefix calls the field named after. self argument will be the BorrowForm class itself and the field argument will be the field you called with validate_

class BorrowForm(FlaskForm):
    ...

    def validate_quantity_borrow(self, field):
        if field.data > (Book.query.filter_by(id=self.book_name.data).first().quantity - sum(i.quantity_borrow for i in Borrow.query.filter_by(book_id=self.book_name.data).all()):
            raise ValidationError("More than we have")

field here is the quantity_borrow attribute of your BorrowForm. When submitted you need to get its data so field.data gives you entered quantity. After that you will get the book chosen by filtering the database with book_id as self.book_name.data which gives you, self as the BorrowForm class itself and book_name attribute of it then, the data of that attribute which is the id of book chosen.

You need to import your database models ,lets say in your forms.py file, and also you need to import ValidationError:

from wtforms.validators import ValidationError

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Ruby, unique hashes in array based on multiple fields

分類Dev

ASP.NET MVC custom multiple fields validation

分類Dev

Where should I put the Custom Validators in Rails 5?

分類Dev

How to use custom password validators beside the django auth password validators?

分類Dev

custom function to form a url to download a document based on key

分類Dev

Conditional custom checkout fields based on product category in Woocommerce

分類Dev

Flask WTform validation on multiple fields

分類Dev

Flask WTForms FieldList with BooleanField

分類Dev

How to provide async parameter to custom Angular validators

分類Dev

How to add input fields to a form dynamically with custom validator?

分類Dev

Custom fields in Razorpay Checkout form

分類Dev

Numbering rows based on multiple fields changes (incluging an "invisible" one) in PostgreSQL

分類Dev

Displaying or hiding multiple fields based on selection dropdown - jquery

分類Dev

Set (custom) fields in Elastic APM for Python with Flask

分類Dev

JavaScript Radio Toggle Show Different Form Fields Based on Checked

分類Dev

Django - Multiple custom models on the same form

分類Dev

Attribute to override generic class based form and use a custom form?

分類Dev

When submitting a Flask WTForms, how can fields be left blank without blanking-out those values from the database table?

分類Dev

Angular Form Custom Validators

分類Dev

Possible to build a flask "WTForms class" conditionally based on language cookie content

分類Dev

Flask Marshmallow JSON fields

分類Dev

Date picker JS: how to have it work on multiple form fields

分類Dev

Django custom form with non-model fields in Admin/AdminInline

分類Dev

C# Enable and Disable Validators on Web Form

分類Dev

Print multiple fields based on partial substring match inside one of the fields

分類Dev

Bash - sort filenames based on multiple fields

分類Dev

Wtforms:validators = [DataRequired()]と[validator.DataRequired()]の違いは何ですか?

分類Dev

Flask-WTForms form.validate()は動的な選択で失敗します

分類Dev

Custom ranking based on multiple criteria in Rails

Related 関連記事

  1. 1

    Ruby, unique hashes in array based on multiple fields

  2. 2

    ASP.NET MVC custom multiple fields validation

  3. 3

    Where should I put the Custom Validators in Rails 5?

  4. 4

    How to use custom password validators beside the django auth password validators?

  5. 5

    custom function to form a url to download a document based on key

  6. 6

    Conditional custom checkout fields based on product category in Woocommerce

  7. 7

    Flask WTform validation on multiple fields

  8. 8

    Flask WTForms FieldList with BooleanField

  9. 9

    How to provide async parameter to custom Angular validators

  10. 10

    How to add input fields to a form dynamically with custom validator?

  11. 11

    Custom fields in Razorpay Checkout form

  12. 12

    Numbering rows based on multiple fields changes (incluging an "invisible" one) in PostgreSQL

  13. 13

    Displaying or hiding multiple fields based on selection dropdown - jquery

  14. 14

    Set (custom) fields in Elastic APM for Python with Flask

  15. 15

    JavaScript Radio Toggle Show Different Form Fields Based on Checked

  16. 16

    Django - Multiple custom models on the same form

  17. 17

    Attribute to override generic class based form and use a custom form?

  18. 18

    When submitting a Flask WTForms, how can fields be left blank without blanking-out those values from the database table?

  19. 19

    Angular Form Custom Validators

  20. 20

    Possible to build a flask "WTForms class" conditionally based on language cookie content

  21. 21

    Flask Marshmallow JSON fields

  22. 22

    Date picker JS: how to have it work on multiple form fields

  23. 23

    Django custom form with non-model fields in Admin/AdminInline

  24. 24

    C# Enable and Disable Validators on Web Form

  25. 25

    Print multiple fields based on partial substring match inside one of the fields

  26. 26

    Bash - sort filenames based on multiple fields

  27. 27

    Wtforms:validators = [DataRequired()]と[validator.DataRequired()]の違いは何ですか?

  28. 28

    Flask-WTForms form.validate()は動的な選択で失敗します

  29. 29

    Custom ranking based on multiple criteria in Rails

ホットタグ

アーカイブ