使用Flask和Jinja2时特定标签的表单数据未通过

1 投票
1 回答
3112 浏览
提问于 2025-04-18 00:34

我正在使用Python、Flask和Jinja来制作一个简单的视频播放列表生成器,这个程序可以直接在树莓派上运行,用户可以通过本地网络创建视频播放列表。它实际上就是编辑一个文本文件,文件中的每一行都是要播放的视频,这些视频会被另一个脚本用来播放。

在同一页面上有两个表单,这里是模板。为了简单起见,它在生成HTML页面时,会逐个数视频名称字符串的字段。

   <body>
 <h2> Add videos to Playlist </h2>
<form action="add" method="POST" >

<select name="video">  
{% set counter = 0 -%} 
{% for videos in videos %}   
<option value="{{ counter + loop.index0 }}">{{ videos }}</option>
{% endfor %}
</select>

<input type="submit" value="Add">

</form>


<h2> Playback List </h2>

<form action="edit" method="POST" >
{% set counter = 0 -%} 
{% for items in playlist %}
{{ items }} 
<input type="hidden" name="filen" value="{{ counter + loop.index0 }}"> 
<input type="submit" name="editype" value="up">
<input type="submit" name="editype" value="down">
<input type="submit" name="editype" value="delete">
<br>
{% endfor %}
<input type="submit" name="editype" value="Next Video">
<input type="submit" name="editype" value="Reset">
</form>



   </body>

当第一个表单“添加”被提交时,它会使用{{ counter + loop.index0 }}生成的数字把文本添加到文本文件中,这个过程运行得很好。

@app.route('/add', methods = ['POST'])
def add():
  vidtoadd = request.form['video']

  vidurl = glob.glob('/home/pi/videos/*.mp4')
  videos = [v.replace('/home/pi/videos/','') for v in vidurl] 

  f = open('playlist.txt','a')
  f.write('%s \n' % videos[int(vidtoadd)])
  f.close()

  playlist = [item.strip() for item in open('playlist.txt', 'r')]

  templateData = {
  'videos' : videos, 'playlist' : playlist
    }

  return render_template('main.html', **templateData)

但是对于另一个表单“编辑”,它却不工作,返回的“fillen”总是0,而不是应该的数字。把{{ items }}放进去是可以的,文件名也能发送,但数字总是返回0!这两个部分之间有什么区别呢?查看页面源代码时,发现“filen”表单的数字是生成出来的,但在POST时却消失了?

@app.route('/edit', methods = ['POST']) 
def edit():
 edit = request.form['editype']
 videotoedit = request.form['filen']
 print '%s %s received!' % (edit,videotoedit)

 if edit == 'Next Video':
     os.system('killall omxplayer.bin')

 vidurl = glob.glob('/home/pi/videos/*.mp4')
 videos = [v.replace('/home/pi/videos/','') for v in vidurl] 

 playlist = [item.strip() for item in open('playlist.txt', 'r')]

 templateData = {
 'videos' : videos, 'playlist' : playlist
    }

 return render_template('main.html', **templateData)

1 个回答

0

你应该把第二个表单标签放到循环里面。

现在的代码会在同一个表单标签里生成多个同名的字段。当你提交这个表单时,只会发送其中一个值(第一个,也就是 0)。

<!-- Following is currently generated by your template. -->

<form action="edit" method="POST">
    <input type="hidden" name="filen" value="0">
    ...other fields here...
    <input type="hidden" name="filen" value="1">
    ...and so on...
</form>

你想要的是每个视频都有不同的表单块。

<!-- Following is what it should be. -->

<form action="edit" method="POST">
    <input type="hidden" name="filen" value="0">
    ...other fields here...
</form>

<form action="edit" method="POST">
    <input type="hidden" name="filen" value="1">
    ...other fields here...
</form>

所以,要修复你的代码中的第二个表单-

<h2> Playback List </h2>

{% set counter = 0 -%} 
{% for items in playlist %}
<form action="edit" method="POST" >
    {{ items }} 
    <input type="hidden" name="filen" value="{{ counter + loop.index0 }}"> 
    <input type="submit" name="editype" value="up">
    <input type="submit" name="editype" value="down">
    <input type="submit" name="editype" value="delete">
</form>
<br>
{% endfor %}
<form action="edit" method="POST" >
    <input type="submit" name="editype" value="Next Video">
    <input type="submit" name="editype" value="Reset">
</form>

撰写回答