Ошибка сборки с переменными и url_for в Flask

На просторах интернета нашел одного-двух человек с похожими проблемами, но решения нигде не видел. Я получаю сообщение об ошибке сборки из приведенного ниже кода/шаблона, но не могу понять, в чем проблема и почему она возникает. Похоже, что шаблон не распознает функцию, но не знаю, почему это происходит. Любая помощь будет принята с благодарностью - уже две ночи бьюсь о клавиатуру.

Функция:

@app.route('/viewproj/<proj>', methods=['GET','POST'])
def viewproj(proj):

...

Выдержка из шаблона:

{% for project in projects %}
  <li>
<a href="{{ url_for('viewproj', proj=project.project_name) }}">
{{project.project_name}}</a></li>
{% else %}
No projects
{% endfor %}

Журнал ошибок: https://gist.github.com/1684250

РЕДАКТИРОВАТЬ: Также хотел указать, что он не распознает переменную «proj» при построении URL-адреса, поэтому просто добавляет значение в качестве параметра. Вот пример: //myproject/viewproj?projname=what+up

Последние несколько строк:

[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/srv/www/myproject.com/myproject/templates/layout.html", line 103, in top-level template code, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     {% block body %}{% endblock %}, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/srv/www/myproject.com/myproject/templates/main.html", line 34, in block "body", referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     <a href="{{ url_for('viewproj', proj=project.project_name) }}">, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/usr/lib/python2.7/dist-packages/flask/helpers.py", line 195, in url_for, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     return ctx.url_adapter.build(endpoint, values, force_external=external), referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/usr/lib/pymodules/python2.7/werkzeug/routing.py", line 1409, in build, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     raise BuildError(endpoint, values, method), referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128] BuildError: ('viewproj', {'proj': '12th'}, None), referer: xx://myproject.com/

person Rob    schedule 26.01.2012    source источник
comment
Вы случайно чертежами не пользуетесь? Определены ли другие маршруты для функции viewproj?   -  person Alex Morega    schedule 26.01.2012
comment
Неа. Я еще довольно рано - есть только 4 просмотра, каждый со своим маршрутом   -  person Rob    schedule 26.01.2012
comment
Попробуйте удалять элементы из своего проекта понемногу, пока не сведете проблему к минимальному тестовому сценарию.   -  person Alex Morega    schedule 27.01.2012
comment
Вы определили viewproj более одного раза? Дублирующиеся имена функций, которые оба маршрутизируются, могут вызвать проблемы такого рода.   -  person ThiefMaster    schedule 01.06.2012


Ответы (7)


url_for ищет функцию, вы передаете ей имя функции, которую хотите вызвать. Итак, вы должны использовать:

{{ url_for('viewproj', proj=xxx) }}

У меня та же проблема. И я решил это:

person atupal    schedule 05.04.2013
comment
Я считаю, что это правильный ответ, потому что у меня тоже такая же проблема. - person newguy; 19.11.2014

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

Просто добавьте '.' перед именем вашего метода в url_for.

Так:

<a href="{{ url_for('.viewproj', proj=project.project_name) }}">

И это должно работать сейчас.

Документ для этого решения от Flask: http://flask.pocoo.org/docs/0.10/api/, и цитирую:

flask.url_for(endpoint, **values) Генерирует URL-адрес заданной конечной точки с помощью предоставленного метода.

Переменные аргументы, неизвестные целевой конечной точке, добавляются к сгенерированному URL-адресу в качестве аргументов запроса. Если значение аргумента запроса равно None, вся пара пропускается. Если чертежи активны, вы можете сократить ссылки на один и тот же чертеж, поставив перед локальной конечной точкой точку (.).

Это будет ссылаться на индексную функцию, локальную для текущего проекта:

url_for('.index')
person Arthur Wang    schedule 25.08.2014
comment
Это то, что мне было нужно. Как-то не интуитивно понятно. Я предполагаю, что всякий раз, когда вы начинаете использовать строки, ссылающиеся на фактические переменные names, такие как имя функции, все становится странным. - person user3391564; 28.09.2014
comment
Это точно для меня! Получал аналогичную ошибку werkzeug.routing.BuildError при вызове url_for(). С точкой (.) Это решает проблему И отображает правильный относительный URL-адрес! Спасибо @Артур Ван - person Devy; 26.06.2015
comment
Полу связанные. У меня были проблемы с BuildError для моей производственной копии, но не для моей локальной копии - я не мог понять, почему. Я использую Flask-Classy, ​​и проблема заключалась в том, что мне нужно было убедиться, что новое представление было зарегистрировано в приложении в основном файле app.py. Для людей с похожими проблемами, которые приходят сюда через Google. - person Reily Bourne; 27.12.2016
comment
Также важно, чтобы модуль с функцией маршрута был импортирован. У меня была такая же ошибка BuildError только потому, что я забыл импортировать модуль представления. - person Roman Susi; 09.05.2018

Я все еще отвечаю на это, хотя на него уже ответили. Причина в ясности. Даже прочитав их, я не мог понять, что происходит, не заглянув в исходный файл url_for().

Чистый пример:

<a href="{{ url_for('viewproj', proj='<projname>') }}">Project name</a>

@app.route('/viewproj/<projname>', methods=['GET','POST'])
def viewproj(proj):
person Victor RENÉ    schedule 18.03.2014

Посмотрите, правильно ли 'project.project_name' разрешается в шаблоне. Правильно ли вы передаете «проекты» шаблону? Вместо этого жестко закодируйте некоторое значение для «proj» и посмотрите, как генерируется URL-адрес. Что-то типа:-

<a href="{{ url_for('viewproj', proj='new_project') }}">new project</a>
person sojin    schedule 27.01.2012
comment
Спасибо за помощь. Когда я передаю 'new_project' в виде строки, она строится как //myproject/viewproj?projname=new_project. Означает ли это, что проблема находится на стороне просмотра/маршрутизации? - person Rob; 27.01.2012
comment
Ваше имя аргумента url_for() в шаблоне не соответствует вашей функции просмотра. Вы используете «projname» в своем шаблоне, а не «proj», как вы определили в своем представлении. вместо {{ url_for('viewproj', projname='new_project') }} используйте {{ url_for('viewproj', proj='new_project') }}. - person sojin; 28.01.2012

Скорее всего, у вас есть более одной маршрутизируемой функции с именем viewproj.

Кроме того, опубликованный вами вывод не соответствует опубликованному вами коду шаблона. myproject/viewproj?projname=what+up означает, что projname=... было передано url_for(), но ваша функция просмотра ожидает proj=...

person ThiefMaster    schedule 01.06.2012

Видя, как вы указываете, какие методы доступны в этой конечной точке, я думаю, вам придется передать нужный метод в url_for.

url_for('viewproj', proj=project.project_name, method='GET')
person Jason Paidoussi    schedule 27.01.2012
comment
Я фактически вытащил спецификацию и получил ту же ошибку. Я пытаюсь указать его исключительно как GET, чтобы увидеть, имеет ли это значение, но, похоже, это не помогает. - person Rob; 27.01.2012
comment
Это также приводит к добавлению метода = 'GET' к URL-адресу: //myproject.com/viewproj?projname=what+up&method=GET - person Rob; 27.01.2012
comment
Не связанный. Методы указываются в вызове маршрута, потому что по умолчанию разрешен только GET. При построении URL вам не нужно указывать метод. - person ThiefMaster; 01.06.2012
comment
Чем URL-адрес GET будет отличаться от URL-адреса POST? - person Markus Unterwaditzer; 08.02.2013

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

Я неправильно "перевел" свой рабочий код:

{% for project in projects %}
    <li>
    <a href="{{ url_for('viewproj', proj='%s') }}"|format(project.project_name)>
    {{project.project_name}}</a>
    </li>
{% else %}
    No projects
{% endfor %}

Интересным эффектом приведенного выше кода является некоторое «заполнение?». добавлено в адрес ссылки

Но когда я подумал об этом, я задался вопросом, добавляет ли url_for какое-либо значение в шаблон? Следующая строка сделает то же самое для вашего тега привязки:

<a href="viewproj/{{ project.project_name }}">{{ project.project_name }}</a> 
person user1431174    schedule 01.06.2012