在html文件中的嵌套Jinja2语句中呈现

h7wcgrx3  于 2023-10-14  发布在  其他
关注(0)|答案(1)|浏览(169)

我的问题的起源是一个表单的验证器函数,它被定义为:

  1. def AirlineICAORequired():
  2. """
  3. Validates whether string is a valid ICAO code
  4. """
  5. message = '''Must be an airline ICAO code. Please refer to: <a id="err-icao" href="{{ url_for('api.airlines') }}" class="link-danger">List of Airlines</a> for a list of airlines with ICAO codes listed.'''
  6. def _airlineicao(form, field):
  7. airline = get_airline(field.data)
  8. if not airline:
  9. raise ValidationError(message)
  10. return _airlineicao

请注意,我正在呈现一个html a标记,我试图将“API.airlines”路线的URL呈现到该标记。我有以下问题要考虑:
1.我不能从from flask import current_app或从app.py定义为app的实际应用示例中使用app_context,原因如下:
a)with current_app.app_context():...仍然会引发RuntimeError,表明我正在应用程序上下文之外工作
B)如果我试图在函数所在的文件(forms.py)中导入from app import app,那么我将遇到一个循环导入错误,因为其他文件,如routes.py(它有一个Blueprint,并在app.py中导入)从这个文件导入。
在html文件中,我将错误消息加载为:

  1. {% for error in initializer_form.initializer.errors %}
  2. <li class="list-group-item list-group-item-danger">
  3. {{ error|safe }}
  4. </li>
  5. {% endfor %}

不幸的是,这会导致以下html行:

  1. <li class="list-group-item list-group-item-danger">
  2. Must be an airline ICAO code. Please refer to: <a id="err-icao" href="{{ url_for('api.airlines') }}" class="link-danger">List of Airlines</a> for a list of airlines with ICAO codes listed.
  3. </li>

对于上下文,initializer_form是设置同一验证器进行验证的形式。
这里还有一张图片,它在网站中的样子,如果点击“航空公司列表”,则会重定向到底部的URL:

其他有用信息:

项目文件结构及相关文件显示:

  1. routelookup/
  2. ├─ Config/
  3. ├─ data/
  4. ├─ static/
  5. ├─ templates/
  6. ├─ api.py
  7. ├─ app.py
  8. ├─ form.py
  9. ├─ routes.py

导入(所有文件的导入都在文件的顶部):

  • app.py:*
  1. # imports
  2. from flask import Flask
  3. from routes import routes
  4. from api import api
  5. from routeparser import reset_contents, fr_api_logout
  6. from Config import config
  7. import atexit
  • form.py:*
  1. # imports
  2. from flask_wtf import FlaskForm
  3. from routeparser import get_airline
  4. from wtforms import StringField, PasswordField, SubmitField
  5. from wtforms.validators import InputRequired, Email, Length, ValidationError
  • routes.py:*
  1. # Imports
  2. from flask import Blueprint, render_template, redirect, url_for
  3. from pathlib import Path
  4. from forms import AirlineInitForm

我想要的
如果我想得到正确的网址到href,而不是如上所示通过图像和第二html代码块,我怎么能考虑到我的问题,如果我想做的事情,通过使用url_for或类似的东西,而不是硬编码它?

编辑1

日期:10/2/23
我创建了一个名为form_validators的新文件,它的部分内容如下所示:

  1. # imports
  2. from flask import url_for
  3. from app import app
  4. from routeparser import get_airline
  5. from wtforms.validators import ValidationError
  6. # Relavant validator to the issue
  7. def AirlineICAORequired():
  8. """
  9. Validates whether string is a valid ICAO code
  10. """
  11. with app.app_context():
  12. message = f'''Must be an airline ICAO code. Please refer to: <a id="err-icao" href="{url_for('api.airlines') }" class="link-danger">List of Airlines</a> for a list of airlines with ICAO codes listed.'''
  13. def _airlineicao(form, field):
  14. airline = get_airline(field.data)
  15. if not airline:
  16. raise ValidationError(message)
  17. return _airlineicao

所有的验证器都被移动到这个文件与相关的进口。
仅导入添加到forms.py

  1. from form_validators import AtLength, AirlineICAORequired
zengzsys

zengzsys1#

所以我解决了我的问题。我要感谢@PGHE尽可能多地帮助我,这激励我更深入地研究我自己的问题。我做了以下修改,其中一些可以在“编辑1”中看到的问题。为了总结这一点,我创建了一个新文件,名为:“forms_validators.py”在这里我将添加所有自定义验证器并将它们分别导入到“forms.py“。至于我需要“修复”的验证器,我做了以下更改,如下面的代码块所示:

  1. def AirlineICAORequired(msg = None):
  2. """
  3. Validates whether string is a valid ICAO code
  4. """
  5. # added method to add custom messages
  6. if isinstance(msg, str):
  7. message = msg
  8. else:
  9. message = "Must be an airline ICAO code. Please double check to make sure it's correct."
  10. def _airlineicao(form, field):
  11. airline = get_airline(field.data)
  12. if not airline:
  13. raise ValidationError(message)
  14. return _airlineicao

这一点很重要,我们将在后面的回答中看到。这只是增加了对添加消息的支持,以便在验证器使表单数据无效时替换显示的默认消息。
根据form.py,我删除了导入:AirlineICAORequired来自form_validators.py,在表单中,我添加了一个方法,在输入字段添加到设置了验证器的表单中之后添加验证器:

  1. # forms.py, lines 20-26 within class AirlineInitForm
  2. def add_validator_to(self, attr, *args):
  3. validator_attr = getattr(self, attr)
  4. if hasattr(validator_attr, "validators"):
  5. validator_attr.validators = validator_attr.validators + list(args)
  6. else:
  7. raise AttributeError("Check again if you inputed the correct attribute name.")

至于路由页面,我确定我将能够使用url_for,而没有任何应用程序上下文等问题。由此可见:

  1. @routes.route('/', methods=['GET', 'POST'], subdomain='application')
  2. def main():
  3. form = AirlineInitForm()
  4. form.add_validator_to(
  5. "initializer",
  6. AirlineICAORequired(f'''
  7. Must be an airline ICAO code. Please refer to: <a id="err-icao" href="{url_for("api.airlines")}" class="link-danger">List of Airlines</a> for a list of airlines with ICAO codes listed.
  8. ''')
  9. )
  10. if form.validate_on_submit():
  11. icao = form.initializer.data
  12. return redirect(url_for('api.generate', icao=icao), code=307)
  13. return render_template('main.html', initializer_form=form)

在检查表单有效性(if form.validate_on_submit())之前,我添加了验证器(AirlineICAORequired),我需要通过后面提到的方法添加到表单类中,使用url_for来获取我想要的航空公司API路线的URL,将其添加到f字符串中,如果验证失败,则会发送错误消息。

展开查看全部

相关问题