这是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_e5d2e3623a42f117
,2_e5d2e3623a42f117
,3_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)
这有效,但我想知道为什么我的初始版本的行为方式
因为您的类BlogPost只声明了一次以及属性hex_token。
hex_token = db.Column(db.String(16), nullable=False, default=secrets.token_hex(8))
定义hex_token时,默认值仅定义一次,并作为默认选项存储在表设置中。每次调用该类的方法时,都无法动态更改默认值。这就是为什么每次调用使用hex_token的类的方法时,hex_token都会返回相同的值。