前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为何我的循环 (for loop) 会执行两次?

为何我的循环 (for loop) 会执行两次?

原创
作者头像
华科云商小徐
发布2024-10-16 10:21:48
1080
发布2024-10-16 10:21:48
举报
文章被收录于专栏:小徐学爬虫

如果你的 for loop 循环执行了两次,而你预期它只执行一次,可能有以下几种常见原因。我们可以检查这些可能的原因,来找出问题的根源。

问题背景

在一个应用中,你有一个 for 循环,它根据表单答案创建一个字典。看起来它被执行了两次,因此第一个字典(它是正确的,你可以看到它)被第二个字典擦除了。你不明白为什么它会被执行两次!有一种感觉,问题可能来自相关的模板(但你可能错了)。

解决方案

问题的原因是模板中有一个隐藏的 CSRF 令牌字段作为表单的一部分。CSRF 令牌用于防止跨站请求伪造攻击,它是一个随机值,在每次请求时都会更新。

但是,在你的模板中,CSRF 令牌字段是作为隐藏字段包含在表单中。这意味着当表单被提交时,CSRF 令牌字段也会被提交。由于 CSRF 令牌的值在每次请求时都会更新,所以每次提交表单时,它都会包含一个不同的 CSRF 令牌值。

CSRF 令牌用于验证请求是否来自合法来源。这意味着当请求包含一个与预期不同的 CSRF 令牌值时,它将被拒绝。

在这种情况下,当表单被提交时,第一个请求包含一个 CSRF 令牌值,但第二个请求包含一个不同的 CSRF 令牌值。因此,第二个请求被拒绝,表单无法成功提交。

为了解决这个问题,你需要将 CSRF 令牌字段从表单中删除。你可以通过在模板中删除以下代码来做到这一点:

代码语言:javascript
复制
<input id="csrf_token" name="csrf_token" type="hidden" value="20131212140726##1a06938d263188231da3de53ec343984b6b1e92b">
<input id="csrf" name="csrf" type="hidden" value="">

删除 CSRF 令牌字段后,表单应该可以正常提交,并且 for 循环将只执行一次。

代码例子

代码语言:javascript
复制
@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)

解决方法

  1. 检查迭代对象或范围:确保迭代的数据没有重复。
  2. 检查函数调用:查看函数是否被重复调用。
  3. 调试与打印:添加调试打印信息(如打印迭代次数或标记函数的调用),帮助你确定循环执行的次数和调用顺序。
  4. 检查事件处理逻辑:如果使用了事件驱动模型,确保事件没有多次触发或处理函数没有被多次绑定。

如果你能提供一些具体代码,我可以帮你更准确地诊断问题。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解决方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档