Flask-SQLAlchemy:模型字段的值由函数生成,并且在我重新启动应用程序之前保持不变

时间:2019-04-15 15:05:13

标签: python flask flask-sqlalchemy

这是models.py

中定义的模型
import os
import secrets

class BlogPost(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(40), nullable=False)
    content = db.Column(db.Text, nullable=False)
    thumbnail = db.Column(db.String(30), nullable=False, default='/static/blog/images/blog_thumbnails/default.png')
    date_added = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    hex_token = db.Column(db.String(16), nullable=False, default=secrets.token_hex(8))


    def save_thumbnail(self):
        if 'thumbnail' in request.files:
            file = request.files['thumbnail']
            filename = f'{self.id}_{self.hex_token}.png'
            file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))

然后routes.py中有一个视图函数,用于添加一个新的BlogPost对象,该对象看起来像这样:

@admin_blueprint.route('/add_blog/', methods=['GET', 'POST'])
def add_blog():
    if request.method == "POST":
        title = request.form['title']
        content = request.form['content']
        post = BlogPost(title=title, content=content)
        db.session.add(post)
        db.session.commit()
        post.save_thumbnail()
        db.session.close()
        return redirect(url_for('blog.index'))
    form = BlogPostForm()
    return render_template('add_blog.html', form=form)

thumbnail模型的BlogPost字段只是用户上传图片的路径,文件名由BlogPost对象的ID加上下划线和随机十六进制标记生成然后使用.save()方法保存图片,但是,假设用户在一个会话中创建了多个BlogPost对象,文件名将仅具有唯一的ID,而没有十六进制,并且从python shell中的使用方式与好吧。

例如,生成的文件名将如下所示: 1_e5d2e3623a42f1172_e5d2e3623a42f1173_e5d2e3623a42f117等...

我认为解决方法是向save_thumbnail方法中添加一个hex_token参数,从模型中完全删除hex_token字段,而是在每次调用视图时生成它。这就是我的意思:

def save_thumbnail(self, hex_token):
        if 'thumbnail' in request.files:
            file = request.files['thumbnail']
            filename = f'{self.id}_{hex_token}.png'
            file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))

routes.py

@admin_blueprint.route('/add_blog/', methods=['GET', 'POST'])
def add_blog():
    if request.method == "POST":
        title = request.form['title']
        content = request.form['content']
        post = BlogPost(title=title, content=content)
        db.session.add(post)
        db.session.commit()

        hex_token = secret.token_hex(8) # new line

        post.save_thumbnail(hex_token)
        db.session.close()
        return redirect(url_for('blog.index'))
    form = BlogPostForm()
    return render_template('add_blog.html', form=form)

这行得通,但是我想知道为什么我的初始版本表现得如此

1 个答案:

答案 0 :(得分:0)

因为您的类BlogPost和属性hex_token仅被声明一次。

hex_token = db.Column(db.String(16), nullable=False, default=secrets.token_hex(8))

定义hex_token时,默认值仅定义一次,并且作为默认选项存储在表设置中。每次调用该类的方法时,都不能动态更改默认值。这就是为什么每次您调用使用hex_token的该类的方法时hex_token返回相同的值的原因。