使用 groupby 和 itemgetter() 将 Python 3.x 代码转换为 jinja2 模板
Converting Python 3.x code into jinja2 template using groupby and itemgetter()
我已经对名为 sorted_cities=[亚特兰大、柏林、伯尔尼、卡尔加里] 的城市列表进行了排序,我正在按 alpha 顺序排序并希望在网络上显示并能够点击城市获取详细信息以及 select 城市以通过电子邮件接收通知。我希望网络上的输出如下所示:
A
Atlanta
B
Berlin
Bern
C
Calgary
我在 Python 3.x 中有以下代码可以正常工作:
sorted_names=sorted(names,key=str.lower)
print(sorted_names)
for letter, words in groupby(sorted_names,key=itemgetter(0)):
print(letter)
for word in words:
print(word)
我在 Jinja2 中创建了这段代码,但它不起作用:
{% block content %}
<div>
<form action="cities" method="post">
{% for group in sorted_names|groupby("letter") %}
<li><b>{{ group.grouper }} </b></li>
{% for word in group.list %}
<input type="checkbox" name="city" value="{{ word }}"> <a href="/{{ word }}">{{ word }}</a><br>
{% endfor %}
{% endfor %}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
这是一个快速测试,可获得您正在寻找的基本功能。我放弃了 @1844144 的评论。但基本上只是将 groupby 元素附加到 python 端的数组并将其传递给 jinja。然后在 jinja 我用 jinja 过滤器做了一个不太聪明的条件事情 (Length of string in Jinja/Flask)
app.py:
from flask import Flask, render_template
from itertools import groupby
from operator import itemgetter
app = Flask(__name__)
@app.route('/')
def main():
names = ['Atlanta','Calgary','Berlin','Austin']
sorted_names = sorted(names, key=str.lower)
grouped = []
for letter, words in groupby(sorted_names,key=itemgetter(0)):
grouped.append(letter)
for word in words:
grouped.append(word)
return render_template('index.html', grouped=grouped)
if __name__ == '__main__':
app.run(debug=True)
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for name in grouped %}
{% if name|length == 1 %}
{{name}}<br>
{% else %}
<a href="/"> {{name}} </a><br>
{%endif%}
{% endfor %}
</body>
</html>
浏览器中的效果如下:
jinja2 中的默认过滤器 groupby
需要该属性来对您的项目进行分组。但是,您提供了 'letter' 属性,但 jinja2 无法理解它,因为您的 names
列表没有这样的属性。
groupby(value, attribute)
Group a sequence of objects by a common attribute.
要重用您的 python 代码,您可以通过 [template_filter
] 向 jinja2 注册一个过滤器(http://flask.pocoo.org/docs/dev/api/#flask.Flt 现在可以使用点 notatask.template_filter)。所以,你可以这样试试:
from itertools import groupby
from operator import itemgetter
from flask import Flask, render_template
app = Flask(__name__)
@app.template_filter()
def groupby_letter(iterable):
return groupby(sorted(iterable), key=itemgetter(0))
@app.route('/')
def index():
names = ['Atlanta','Calgary','Berlin','Austin']
return render_template('index.html', names=names)
if __name__ == '__main__':
app.run(debug=True)
并像这样在模板中使用过滤器:
{% for key, group in names|groupby_letter %}
<li><b>{{ key }}</b></li>
{% for word in group %}
<p>{{ word }}</p>
{% endfor %}
{% endfor %}
另一种方法是,如果您仍想使用 groupby
过滤器,则需要对 names
做一些事情。我们需要构建一个列表字典,每个字典包含一个 'first_letter' 键,我们将在使用 groupby
过滤器时将其用作组属性。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
names = ['Atlanta','Calgary','Berlin','Austin']
name_dicts = [{'first_letter': name[0], 'name': name} for name in names]
return render_template('index.html', name_dicts=name_dicts)
if __name__ == '__main__':
app.run(debug=True)
并在您的模板中使用 groupby
过滤器,如下所示:
{% for group in name_dicts|groupby('first_letter') %}
<li><b>{{ group.grouper }}</b></li>
{% for item in group.list %}
<p>{{ item.name }}</p>
{% endfor %}
{% endfor %}
我已经对名为 sorted_cities=[亚特兰大、柏林、伯尔尼、卡尔加里] 的城市列表进行了排序,我正在按 alpha 顺序排序并希望在网络上显示并能够点击城市获取详细信息以及 select 城市以通过电子邮件接收通知。我希望网络上的输出如下所示:
A
Atlanta
B
Berlin
Bern
C
Calgary
我在 Python 3.x 中有以下代码可以正常工作:
sorted_names=sorted(names,key=str.lower)
print(sorted_names)
for letter, words in groupby(sorted_names,key=itemgetter(0)):
print(letter)
for word in words:
print(word)
我在 Jinja2 中创建了这段代码,但它不起作用:
{% block content %}
<div>
<form action="cities" method="post">
{% for group in sorted_names|groupby("letter") %}
<li><b>{{ group.grouper }} </b></li>
{% for word in group.list %}
<input type="checkbox" name="city" value="{{ word }}"> <a href="/{{ word }}">{{ word }}</a><br>
{% endfor %}
{% endfor %}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
这是一个快速测试,可获得您正在寻找的基本功能。我放弃了 @1844144 的评论。但基本上只是将 groupby 元素附加到 python 端的数组并将其传递给 jinja。然后在 jinja 我用 jinja 过滤器做了一个不太聪明的条件事情 (Length of string in Jinja/Flask)
app.py:
from flask import Flask, render_template
from itertools import groupby
from operator import itemgetter
app = Flask(__name__)
@app.route('/')
def main():
names = ['Atlanta','Calgary','Berlin','Austin']
sorted_names = sorted(names, key=str.lower)
grouped = []
for letter, words in groupby(sorted_names,key=itemgetter(0)):
grouped.append(letter)
for word in words:
grouped.append(word)
return render_template('index.html', grouped=grouped)
if __name__ == '__main__':
app.run(debug=True)
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for name in grouped %}
{% if name|length == 1 %}
{{name}}<br>
{% else %}
<a href="/"> {{name}} </a><br>
{%endif%}
{% endfor %}
</body>
</html>
浏览器中的效果如下:
jinja2 中的默认过滤器 groupby
需要该属性来对您的项目进行分组。但是,您提供了 'letter' 属性,但 jinja2 无法理解它,因为您的 names
列表没有这样的属性。
groupby(value, attribute)
Group a sequence of objects by a common attribute.
要重用您的 python 代码,您可以通过 [template_filter
] 向 jinja2 注册一个过滤器(http://flask.pocoo.org/docs/dev/api/#flask.Flt 现在可以使用点 notatask.template_filter)。所以,你可以这样试试:
from itertools import groupby
from operator import itemgetter
from flask import Flask, render_template
app = Flask(__name__)
@app.template_filter()
def groupby_letter(iterable):
return groupby(sorted(iterable), key=itemgetter(0))
@app.route('/')
def index():
names = ['Atlanta','Calgary','Berlin','Austin']
return render_template('index.html', names=names)
if __name__ == '__main__':
app.run(debug=True)
并像这样在模板中使用过滤器:
{% for key, group in names|groupby_letter %}
<li><b>{{ key }}</b></li>
{% for word in group %}
<p>{{ word }}</p>
{% endfor %}
{% endfor %}
另一种方法是,如果您仍想使用 groupby
过滤器,则需要对 names
做一些事情。我们需要构建一个列表字典,每个字典包含一个 'first_letter' 键,我们将在使用 groupby
过滤器时将其用作组属性。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
names = ['Atlanta','Calgary','Berlin','Austin']
name_dicts = [{'first_letter': name[0], 'name': name} for name in names]
return render_template('index.html', name_dicts=name_dicts)
if __name__ == '__main__':
app.run(debug=True)
并在您的模板中使用 groupby
过滤器,如下所示:
{% for group in name_dicts|groupby('first_letter') %}
<li><b>{{ group.grouper }}</b></li>
{% for item in group.list %}
<p>{{ item.name }}</p>
{% endfor %}
{% endfor %}