首页 > 解决方案 > 在 Flask 和 Flask SQLAlchemy 中处理重复用户

问题描述

我想允许匿名用户在博客中发表他们的评论,而不需要他们登录或注册。一位匿名用户可以在后续访问期间使用相同的凭据发布多条评论。但是,我SQLAlchemy IntegrityError在第二次尝试时得到了。

我有一个简单的表格,一个简单的模型和一个基本的路线。

comment.py

class CommentForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    comment = TextAreaField('Comment', validators=[DataRequired()])
    submit = SubmitField('Post')

models.py

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    posts = db.relationship('Post', backref='author', lazy='dynamic')

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(500))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) 
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

route.py

@app.route('/personal_blog', methods = ['GET', 'POST'])
def personal_blog():
    form = CommentForm()
    if form.validate_on_submit():
        user = User(username = form.username.data, email = form.email.data)        
        post = Post(body = form.comment.data, author = user)
        db.session.add(user)
        db.session.add(post)
        db.session.commit()
        flash('Your comment is now live!')  
        return redirect(url_for('personal_blog', _anchor='translate-hover'))  
    posts = Post.query.order_by(Post.timestamp.desc()).all()
    return render_template('personal_blog.html', form = form, posts = posts)

我尝试了几种建议的解决方案,而我来到的壁橱是向表单添加验证,例如:

class CommentForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    comment = TextAreaField('Comment', validators=[DataRequired()])
    submit = SubmitField('Post')

    def __init__(self, original_username, *args, **kwargs):
        super(CommentForm, self).__init__(*args, **kwargs)
        self.original_username = original_username

    def validate_username(self, username):
        if username.data != self.original_username:
            user = User.query.filter_by(username=self.username.data).first()
            if user is not None:
                raise ValidationError('Please use a different username.')

但是,这需要添加@app.route('/personal_blog/<username>')它基本上不适用于我的情况。我想让这个匿名用户发布后续评论,而无需更改用户名电子邮件

就个人而言,我尝试在路由 ( if user.username is not None: flash('Use different credentials!')) 中添加验证,以通知用户他们尝试使用的电子邮件或用户名已被使用,并且它有效,但这不是我希望应用程序执行的操作。用户可以简单地使用与以前完全相同的凭据。如何做到这一点?

标签: pythonflaskflask-sqlalchemy

解决方案


解决方案是从表中删除unique约束。User

代替:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True) <----------here
    email = db.Column(db.String(120), index=True, unique=True) <----------here
    posts = db.relationship('Post', backref='author', lazy='dynamic')

我有这个:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True) <----------here
    email = db.Column(db.String(120), index=True) <----------here
    posts = db.relationship('Post', backref='author', lazy='dynamic')

一旦我更新数据库,更改就会生效,并且我可以允许单个匿名用户使用相同的凭据发布多个评论。


推荐阅读