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

问题描述 投票:0回答:1

这是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而不是hex,并且它与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)

这有效,但我想知道为什么我的初始版本的行为方式

python flask flask-sqlalchemy
1个回答
0
投票

因为您的类BlogPost只声明了一次以及属性hex_token。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.