在view function里获得指定model随机id,无法存储


#1

我在route.py里面写了一个work function, 它的作用是随机获得一个model(Partition)里面符合要求的对象,然后读取这个对象的数据,从而生成一个动态的表单PostForm()和提供图片的url给template显示。

我的构思是用户填写完按下submit之后,去validate这个form。然后将这个随机对象的id存到一个叫做post的model里面。但是我现在的代码它并不能存当前随机的id,只能够存下一个随机的id。

我确定了是因为每次按submit它都再一次call了work,所以生成了新的random对象,以至于没有办法走进valid_on_submit的条件。我想知道怎么解决这个问题。

代码如下

@app.route('/work', methods=['GET','POST'])
@login_required
def work():
	# first of all, return a random partition id 
	# and check it has been edited by current_user or not
	
	rand_part = Partition.query.filter(Partition.count < 2).order_by(func.random()).first()
	col_num = rand_part.getcolumn()

	# considering post form as a temporal form
	# which may varies due to different partition have different columns
	class PostForm(FlaskForm):
		pass

	for i in range(0,col_num):
		setattr (PostForm,'field'+str(i), 
				StringField('content', validators =[DataRequired()]))

	setattr(PostForm, 'submit', SubmitField('Next'))

	form = PostForm()
	if request.method == 'POST':
		if form.validate_on_submit():
			templist = ""
			for field in form:
				if field.type == 'StringField':
					templist  += ';%s' % field.data
			
			newpost = Post(user_id = current_user.getid(),
							part_id = rand_part.getid(),
							content = templist)
			# commit to db
			db.session.add(newpost)

			# add editor
			partcount = rand_part.getcount()
				
			if partcount == 0:
				rand_part.editor1 = current_user.id
			elif partcount == 1:
				rand_part.editor2 = current_user.id

			# increase partition count by 1
			rand_part.count = partcount + 1
			db.session.commit()
			flash('Post has been sent successfully, try next one!', 'success')
			return redirect(url_for('work'))
		else:
			flash('unsuccessful post, sorry')
			return redirect(url_for('work'))

	return render_template('workPage.html', form = form, part = rand_part)

#2

我来分析一下,第一,获取符合条件的对象的随机id这一步需要放到request == 'GET’的条件下,然后,当你生成PostForm表单的时候,需要生成一个隐藏的字段, 字段的值设置为 rand_part.getid()。当 request.method == ‘POST’ , 生成newpost的时候, part_id的值从form的那个隐藏字段那里取,以上个人看法,可能是错的


#3

第一点的思路是一样的,我现在使用了一个global cur_part来存随机id,在request=='GET’的时候我才给这个global变量赋值。但是我觉得用global感觉是有点丑陋。而且我现在莫名其妙就不能够通过cur_part.name = "newname"给它更新它里面的值。
所以我在思考怎么改进,至于你说的隐藏字段,我没有太明白,如果是在生成PostForm的时候设置,这个时候是没有走进validate_on_submit()的,也就是说rand_part一更新了,它也会跟着更新,这样就没有意义了。


#4

处理GET请求,生成PostForm时

setattr(PostForm, 'id', HiddenField('hide', render_kw={'value':rand_part.getid() }))

这样PostForm就包含了第一次处理GET请求时生成的id值, 当再次提交Post请求时,

newpost = Post(user_id = current_user.getid(),
							part_id = form.id.data ,
							content = templist)

#5

感谢:pray:这个看上去挺合理的,感觉比我的global好多了,让我试一下这个做法