Синтаксис вложенного цикла на страницах сервера Python

Я просто пытаюсь написать небольшую веб-страницу, которая может анализировать некоторый текст с помощью регулярного выражения и возвращать полученные совпадения в таблицу. Это первый раз, когда я использовал python для веб-разработки, и я должен сказать, что это выглядит грязно.

Мой вопрос: почему я получаю вывод только для последнего совпадения в моем наборе данных? Я полагаю, что это должно быть потому, что вложенные циклы не отформатированы правильно.

Вот данные, которые я предоставляю:

groups - это просто id, соответствующий группе регулярных выражений, и это имя для предоставления заголовка таблицы.

шаблон это что-то вроде:

(\d+)\s(\S+)\s(\S+)$

и данные:

12345 SOME USER
09876 SOMEONE ELSE
54678 ANOTHER USER

Моя простая страница:

<%
import re
pattern = form['pattern']
p = re.compile(pattern)
data = form['data']

matches = p.finditer(data)

lines = form['groups'].split("\n")
groupids ={}
for line in lines:
  key, val = line.split(' ')
  groupids[int(key.strip())] = val.strip()

%>
<html>
<table style="border-width:1px;border-style:solid;width:60%;">
<tr>
<%
for k,v in groupids.iteritems():%>
<th style="width:30px;text-align:center"><%= v %></th>
<%
# end
%>
</tr>
<%
for match in matches:
  #begin
%><tr>
<%
for i in range(1, len(match.groups())+1):
  #begin
%>
  <td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= match.group(i) %></td>
<%
  #end
# end
%>
</tr>

</table>
</html>

редактировать

Ниже тест, который я провел

Код:

import re
pattern = "(\d\d\d\d\d)\s(\S+)\s(\S+)"

p = re.compile(pattern)

data = """12345 TESTS USERS
34567 TESTS USERS
56789 TESTS USERS"""

groups = """1 PIN
2 FNAME
3 LNAME"""

matches = p.finditer(data)

lines = groups.split("\n")

print lines
groupids ={}
for line in lines:
  key, val = line.split(' ')
  groupids[int(key.strip())] = val.strip()


for k,v in groupids.iteritems():
  print "%s\t" % v,
print ''

for match in matches:
  for i in range(1, len(match.groups())+1):
    print "%s\t" % match.group(i),
  print ''

Выход:

PIN     FNAME   LNAME
12345   TESTS   USERS
34567   TESTS   USERS
56789   TESTS   USERS

2 ответа

Решение
<%
for match in matches:
  #begin
%><tr>
<%
for i in range(1, len(match.groups())+1):
  #begin
%>
  <td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= match.group(i) %></td>
<%
  #end
# end
%>

Да, у вас там нет вложенной петли. Вместо этого у вас есть петля matches который выводит "\n", затем второй цикл range(...) это работает только после того, как первый закончил. Второе не находится внутри первого, потому что оно не имеет отступов, чтобы сказать это.

Из документа, я думаю, вы должны сказать следующее:

<%
for match in matches:
    # begin
%><tr><%
    for group in match.groups():
        # begin
%><td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= group %></td><%
    # end
%></tr><%
# end
%>

Но я могу только согласиться с вашим "грязным" комментарием: если PSP требует, чтобы вы пытали отступ в своем HTML, чтобы он соответствовал структуре вашего Python, вот так, это действительно Doing It Wrong, и вы должны искать другой, менее ужасный шаблонизатор синтаксис. Существует множество языков шаблонов для Python, которые имеют более разумный синтаксис для управляющих структур. В качестве примера, тот, который я использую выше, будет выглядеть так:

<px:for item="match" in="matches"><tr>
    <px:for item="group" in="match.groups()">
        <td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;">
            <?_ group ?>
        </td>
    </px:for>
</tr></px:for>

Я не уверен насчет взаимодействия с движком шаблонов, но python ожидает, что внутренний цикл будет иметь отступ под содержащим циклом.

Попробуйте отформатировать его таким образом и посмотрите, работает ли он.

<%
for match in matches:
    %><tr><%
    for i in range(1, len(match.groups())+1):
        %><td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= match.group(i) %></td><%
%>

Или некоторые такие. Выше приведено "IndentationError: unindent не соответствует ни одному внешнему уровню отступа", поэтому попробуйте:

<%
for match in matches:
    %><tr><%
    for i in range(1, len(match.groups())+1):
        %><td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= match.group(i) %></td><%

%>

или же

<%
for match in matches:
    %><tr><%
    for i in range(1, len(match.groups())+1):
        %><td style="border-style:solid;border-width:1px;border-spacing:0px;text-align:center;"><%= match.group(i) %></td><%
pass
%>

или какая-то комбинация. Ваша проблема заключается в указании Python, где заканчивается цикл. Чтобы сделать это, вы должны найти способ заставить шаблонизатор создавать правильный python с правильным отступом.

Кроме того, если вы можете получить сгенерированный код, вы можете разделить проблему пополам: сначала поработайте с сгенерированным кодом, чтобы выяснить, что примет python, а затем поработайте с шаблоном, чтобы заставить его произвести это.

Другие вопросы по тегам