如果你的 for loop
循环执行了两次,而你预期它只执行一次,可能有以下几种常见原因。我们可以检查这些可能的原因,来找出问题的根源。
问题背景
在一个应用中,你有一个 for 循环,它根据表单答案创建一个字典。看起来它被执行了两次,因此第一个字典(它是正确的,你可以看到它)被第二个字典擦除了。你不明白为什么它会被执行两次!有一种感觉,问题可能来自相关的模板(但你可能错了)。
解决方案
问题的原因是模板中有一个隐藏的 CSRF 令牌字段作为表单的一部分。CSRF 令牌用于防止跨站请求伪造攻击,它是一个随机值,在每次请求时都会更新。
但是,在你的模板中,CSRF 令牌字段是作为隐藏字段包含在表单中。这意味着当表单被提交时,CSRF 令牌字段也会被提交。由于 CSRF 令牌的值在每次请求时都会更新,所以每次提交表单时,它都会包含一个不同的 CSRF 令牌值。
CSRF 令牌用于验证请求是否来自合法来源。这意味着当请求包含一个与预期不同的 CSRF 令牌值时,它将被拒绝。
在这种情况下,当表单被提交时,第一个请求包含一个 CSRF 令牌值,但第二个请求包含一个不同的 CSRF 令牌值。因此,第二个请求被拒绝,表单无法成功提交。
为了解决这个问题,你需要将 CSRF 令牌字段从表单中删除。你可以通过在模板中删除以下代码来做到这一点:
<input id="csrf_token" name="csrf_token" type="hidden" value="20131212140726##1a06938d263188231da3de53ec343984b6b1e92b">
<input id="csrf" name="csrf" type="hidden" value="">
删除 CSRF 令牌字段后,表单应该可以正常提交,并且 for 循环将只执行一次。
代码例子
@app.route('/torrent/<tor_id>', methods=['GET', 'POST'])
@login_required
def torrent(tor_id):
user = g.user
# fetch informations about the torrent from transmission
torrent = client.get_torrent(tor_id)
# fetch information about the torrent from DB
tordb = Torrent.query.filter_by(hashstring=torrent.hashString).first()
if tordb.user != unicode(user):
return render_template("404.html")
else:
###
# error = ''
if torrent.error == 1:
torrent.error = 'tracker warning'
if torrent.error == 2:
torrent.error = 'tracker error'
if torrent.error == 3:
torrent.error = 'local error'
###
# if torrent.seedRatioMode == 0:
# torrent.seedRatioMode = 'Global ratio limit'
# if torrent.seedRatioMode == 1:
# torrent.seedRatioMode = 'Individual ratio limit'
# if torrent.seedRatioMode == 2:
# torrent.seedRatioMode = 'Unlimited seeding'
control = TorrentForm(bandwidthpriority=torrent.bandwidthPriority,
ratiomode=torrent.seedRatioMode)
###
for file_x in client.get_files(tor_id)[torrent.id]:
f_form = TorrentFileDetails(csrf_enabled=False)
f_form.key = file_x
f_form.filename = unicode(client.get_files(tor_id)[torrent.id][file_x]['name'])
f_form.priority = client.get_files(tor_id)[torrent.id][file_x]['priority']
f_form.size = client.get_files(tor_id)[torrent.id][file_x]['size']
f_form.completed = client.get_files(tor_id)[torrent.id][file_x]['completed']
f_form.selected = client.get_files(tor_id)[torrent.id][file_x]['selected']
control.files.append_entry(f_form)
# the form is not validated because of the csrf trick !
if control.is_submitted():
update = False
# by default, ratio limit can be updated !
update_ratio_limit = True
if control.ratiomode.data != torrent.seedRatioMode:
if control.ratiomode.data == '0':
torrent.seed_ratio_mode = 'global'
# we don't allow anymore the ratio limit to be updated : the ratiolimit will be the gloabal one !
update_ratio_limit = False
if control.ratiomode.data == '1':
torrent.seed_ratio_mode = 'single'
if control.ratiomode.data == '2':
torrent.seed_ratio_mode = 'unlimited'
# we don't allow anymore the ratio limit to be updated : the ratiolimit will be the gloabal one !
update_ratio_limit = False
update = True
# if we are still allowed to update ratio limit
# eg : we haven't touched ratiomode in form - update_ratio_limit is still at its default : true
# or it has been changed to single mode
if update_ratio_limit:
if control.ratiolimit.data != torrent.seedRatioLimit:
torrent.seed_ratio_limit = float(control.ratiolimit.data)
torrent.seed_ratio_mode = 'single'
update = True
if control.downloadlimit.data != torrent.downloadLimit:
torrent.download_limit = int(control.downloadlimit.data)
update = True
if control.uploadlimit.data != torrent.uploadLimit:
torrent.upload_limit = int(control.uploadlimit.data)
update = True
if control.bandwidthpriority.data != torrent.bandwidthPriority:
if control.bandwidthpriority.data == '-1':
torrent.priority = 'low'
if control.bandwidthpriority.data == '1':
torrent.priority = 'high'
if control.bandwidthpriority.data == '0':
torrent.priority = 'normal'
update = True
# we use the ID returned by transmission itself ! Not the hashString.
# the first torrent.id is to say which torrent we are talking about. Transmission gives us a dict containing the info for the torrents asked.
# so the dict contains ONE torrent info
# but still, begin with the torrent.id, this is why the second torrent.id
files_answers = {}
for file_un in control.files:
# create a dict that contains the new priority for each file according to the form
file_answer = {}
if file_un.priority.data != client.get_files(tor_id)[torrent.id][int(file_un.key.data)]['priority']:
file_answer['priority'] = file_un.priority.data
if file_un.selected.data != client.get_files(tor_id)[torrent.id][int(file_un.key.data)]['selected']:
file_answer['selected'] = file_un.selected.data
# append the dict to the general dict previously created (files_answers).
# the key is the ID of the file itself ! >> no value name !
files_answers[int(file_un.key.data)] = file_answer
# finally, we create the last dict which will contain only one value : the files_answers dict !
answer = {}
answer[int(torrent.id)] = files_answers
update = True
client.set_files(answer)
if update:
torrent.update()
# start_stop_torrent(tor_id)
return render_template("torrent.html", title=torrent.name, user=user, torrent=torrent, control=control)
如果你能提供一些具体代码,我可以帮你更准确地诊断问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。