为什么我的'for'循环完成了两次?

时间:2013-12-08 17:05:22

标签: python flask jinja2

在我的应用程序中,我有一个for循环,根据表单答案创建一个字典。它似乎被执行了两次,所以第一个dict(这是好的,我可以看到它)被第二个删除。我不明白为什么它被执行了两次!

我觉得问题来自模板相关(但我可能错了)。

这是模板:

{% extends "base.html" %}
{% block content %}
<h1>{{torrent.name}} is {{torrent.status}}</h1>

<form class="uk-form uk-form-row uk-form-horizontal" action="/torrent/{{torrent.hashString}}" method="post" name="torrent" >
{{control.hidden_tag()}}
 <p>
<ul class="uk-breadcrumb">
    <li><a href='/start/{{torrent.hashString}}'>Start</a></li>
    <li><a href='/stop/{{torrent.hashString}}'>Stop</a></li>
</ul>
<button class="uk-button" name="button" id="button" type="submit" value="update">Update</button>
</p>

 <div class="uk-grid">
<div class="uk-width-1-3 uk-panel uk-panel-header">
    <h3 class="uk-panel-title">Status</h3>
    <ul class="uk-list">
    <li>Progress of download process : {{torrent.progress}} %</li>
    <li>Priority : {{control.bandwidthpriority(default=torrent.bandwidthPriority)}}</li>
    <li>Date of start : {{momentjs(torrent.addedDate).calendar()}}</li>
    <li>Last start date : {{torrent.startDate}}</li>
    {# <li>Estimated remaining time : {{torrent.eta}}</li>
    <li>Leechers : {{torrent.leechers}}</li>
    <li>Seeders : {{torrent.seeders}}</li> #}
    </ul>
</div>
    ...
all kind of info but no controls


  </div>

  <p>Total size : {{torrent.totalSize|filesize}}</p>

 {% if torrent.error != 0 %}
<p>There's a {{torrent.error}} :<br />
{{torrent.errorString}}</p>
{% endif %}

<h2>Files</h2>
<table class="uk-table">
    <tr>
        <th>File name</th>
        <th>Completed / Size</th>
        <th>Selected</th>
        <th>Priority</th>
    </tr>

    {% for file in control.files %}
    <tr>
    {{file.key}}
        <td>{{file.filename.data}}</td>
        <td>{{file.completed.data}} / {{file.size.data}}</td>
        <td>{{file.selected}}</td>
        <td>{{file.priority}}</td>
        {# <td><button type="submit">Send</button></td> #}
    </tr>
    {% endfor %}
</table>
</form>
{% endblock %}

这是视图:

@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: <<<< This is this loop which is executed two times !
            # 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)

最后是表格:

# each individual file in the torrent have its own priority, thus, we need to manage   them individually !
 class TorrentFileDetails(Form):
key  = HiddenField('key')
filename = HiddenField('filename')
size     = HiddenField('size')
completed = HiddenField('completed')
selected = BooleanField('selected')
priority = SelectField(u'File priority',choices=[('low','low'),('normal','normal'),('high','high')])

# we desactivate the csrf cause this particular form is within the TorretForm, so it can't be several csrf at the same time !
def __init__(self, *args, **kwargs):
    kwargs['csrf_enabled'] = False
    super(TorrentFileDetails, self).__init__(*args, **kwargs)

class TorrentForm(Form):
hidden      = HiddenField('hidden')
ratiolimit  = DecimalField("ratio")
ratiomode   = SelectField(u'Ratio mode', choices=[(0,'Global ratio limit'),(1,'Individual ratio limit'),(2,'Unlimited seeding')])
downloadlimit   = DecimalField("down")
uploadlimit     = DecimalField("up")
bandwidthpriority = SelectField(u'Torrent priority', choices=[( -1,'low'),(0,'normal'),(1,'high')])

# we append each individual file form to this, as we don't know how many there is in each torrent !
files       = FieldList(FormField(TorrentFileDetails))

例如,这是iso torrent的html页面/表单。所以洪流中有一个文件!

   <form class="uk-form uk-form-row uk-form-horizontal" action="/torrent/e3811b9539cacff680e418124272177c47477157" method="post" name="torrent" >
   <div style="display:none;"><input id="csrf_token" name="csrf_token" type="hidden" value="20131212140726##1a06938d263188231da3de53ec343984b6b1e92b"><input id="csrf" name="csrf" type="hidden" value=""></div>
  <p>
        <ul class="uk-breadcrumb">
         <li><a href='/start/e3811b9539cacff680e472177c47477157'>Start</a></li>
         <li><a href='/stop/e3811b9539cacff680e472177c47477157'>Stop</a></li>
        </ul>
        <button class="uk-button" name="button" id="button" type="submit" value="update">Update</button>
  </p>

  <div class="uk-grid">
<div class="uk-width-1-3 uk-panel uk-panel-header">
    <h3 class="uk-panel-title">Status</h3>
    <ul class="uk-list">
    <li>Total size : 0.9 GiB</li>
    <li>Progress of download process : 100.0 %</li>
    <li>Priority : <select id="bandwidthpriority" name="bandwidthpriority"><option value="-1">low</option><option selected value="0">normal</option><option value="1">high</option></select></li>

    </ul>
</div>
<div class="uk-width-1-3 uk-panel uk-panel-header">
    <h3 class="uk-panel-title">Downloading</h3>
    <ul class="uk-list">
    <li>Number of peers sending to us : 0</li>
    <li>Download rate : 0 bits/s</li>
    <li>Download limit : <input class="uk-form-width-small" id="downloadlimit" name="downloadlimit" type="number" value="100"> KB/s</li>
    <li></li>
    <li>Corrupt data downloaded : 0.0 KiB</li>
    </ul>
</div>
<div class="uk-width-1-3 uk-panel uk-panel-header">
    <h3 class="uk-panel-title">Uploading</h3>
    <ul class="uk-list">
    <li>Number of peers getting from us : 0</li>
    <li>Upload rate : 0 bits/s</li>
    <li><label class="uk-form-label" for="">Upload limit :</label><div class="uk-form-controls"><input class="uk-form-width-small" id="uploadlimit" name="uploadlimit" type="number" value="100"> KB/s</div></li>
    <li></li>
    <li><label class="uk-form-label" for="">Ratio mode :</label><div class="uk-form-controls"><select id="ratiomode" name="ratiomode"><option selected value="0">Global ratio limit</option><option value="1">Individual ratio limit</option><option value="2">Unlimited seeding</option></select></div></li>
    <li><label class="uk-form-label" for="">Ratio limit :</label><div class="uk-form-controls"><input class="uk-form-width-small" id="ratiolimit" name="ratiolimit" step="0.1" type="number" value="2"></div></li>
    <li>Ratio : 0.0</li>
    </ul>
</div>
 </div>



<h2>Files</h2>
<table class="uk-table">
    <tr>
        <th>File name</th>
        <th>Completed / Size</th>
        <th>Selected</th>
        <th>Priority</th>
    </tr>


    <tr>
    <input id="files-0-key" name="files-0-key" type="hidden" value="0">
        <td>ubuntu-13.10-desktop-amd64.iso</td>
        <td>835584 / 925892608</td>
        <td><input checked id="files-0-selected" name="files-0-selected" type="checkbox" value="y"></td>
        <td><select id="files-0-priority" name="files-0-priority"><option value="low">low</option><option selected value="normal">normal</option><option value="high">high</option></select></td>

    </tr>

</table>
 </form>

</div>
 </body>
</html> 

1 个答案:

答案 0 :(得分:0)

循环不会这样做两次!

当点击按钮并执行validate_on_submit时,帖子包含双重答案:用户想要给出的答案以及原始数据!

在按下按钮之前:

[{'completed': 9705687, 'selected': True, 'filename': u'WADs/Doom WADs.7z', 'priority': u'normal', 'key': 0, 'size': 9705687}, 
{'completed': 4571349, 'selected': True, 'filename': u'WADs/Heretic WADs.7z', 'priority': u'normal', 'key': 1, 'size': 4571349}, 
{'completed': 7757653, 'selected': True, 'filename': u'WADs/Hexen WADs.7z', 'priority': u'normal', 'key': 2, 'size': 7757653}]
按下按钮后

[{'completed': u'', 'selected': True, 'filename': u'', 'priority': u'normal', 'key': u'0', 'size': u''}, 
{'completed': u'', 'selected': True, 'filename': u'', 'priority': u'normal', 'key': u'1', 'size': u''}, 
{'completed': u'', 'selected': True, 'filename': u'', 'priority': u'normal', 'key': u'2', 'size': u''}, 
{'completed': 9705687, 'selected': True, 'filename': u'WADs/Doom WADs.7z', 'priority': u'normal', 'key': 0, 'size': 9705687}, 
{'completed': 4571349, 'selected': True, 'filename': u'WADs/Heretic WADs.7z', 'priority': u'normal', 'key': 1, 'size': 4571349}, 
{'completed': 7757653, 'selected': True, 'filename': u'WADs/Hexen WADs.7z', 'priority': u'normal', 'key': 2, 'size': 7757653}]

因此,经过处理的答案会经历好的一次,然后遍历原始数据,并擦除我们想要传递的好的值。