简体   繁体   中英

Validate current_user if it is already in DB

I can't get validation error to be displayed, only IntegrityError from SQLAlchemy

(sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: Booking.username).

I have two tables in DB, one is a list of registered users, another one is a list of logged in users where they can book time thru FlaskForm with RadioFields. I think I have mistake in this function def validate_booking (self)

I need to check if the current_user already booked time then he cannot do another booking

I moved validation function into LoginForm instead and this seems to be working. It validates before the user jumps into next booking page. Not exactly how I wanted having the validation in booking page though.

models.py

class User(db.Model, UserMixin):
    __tablename__ = 'Employees'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    code = db.Column(db.String(20), nullable=False)

    def __repr__(self):
        return f"User('{self.username}', '{self.code}')"


class Book(db.Model, UserMixin):
    __tablename__ = 'Booking'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    choice = db.Column(db.String(30), nullable=False)

    def __repr__(self):
        return f"Book('{self.username}, '{self.choice}')"

forms.py

    class LoginForm(FlaskForm):
        username = StringField('Name', validators=[DataRequired(), Length(min=2, max=20)])
        code = StringField('Code', validators=[DataRequired()])
        submit = SubmitField('Book time')

        def validate_username(self, username):
            user = Book.query.filter_by(username=username.data).first()
            if user:
                raise ValidationError('You have registered your car today')
    
    class BookingForm(FlaskForm):
        book = RadioField('Label', choices=[('Station_1_morning', '07:00-11:00'), ('Station_1_afternoon', '11:00-15:00'),
                                            ('Station_2_morning', '07:00-11:00'), ('Station_2_afternoon', '11:00-15:00'),
                                            ('Station_3_morning', '07:00-11:00'), ('Station_3_afternoon', '11:00-15:00')],
                          coerce=str, validators=[InputRequired()])
        submit = SubmitField('Register time')
    
        

routes.py

@app.route("/booking", methods=['POST', 'GET'])
@login_required
def booking():
    session.permanent = True
    app.permanent_session_lifetime = timedelta(seconds=5)
    form = BookingForm()
    if form.validate_on_submit():
        book = Book(username=current_user.username, choice=form.book.data)
        db.session.add(book)
        db.session.commit()
        flash('Your time is registered', 'success')
    return render_template('booking.html', title='Booking', form=form)

I don't see the error. You could add a print (user) in the validation function to see what's in there.

Anyway this is still open to a race condition: if the same user books in another request between the check ("validation")and the commit. As a general rule, I'd rather try to commit and catch the integrity error. It can be a bit tricky to build a meaningful message from an integrity error exception object (I mean get the name of the offending field(s) from the object). Of course if you know for sure only one constraint applies, you may hardcode the message.

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