Flask技术问询:如何自定义未被跟随的302重定向生成的HTML?
自定义Flask未跟随的302重定向返回的HTML
哈哈,这个坑我之前踩过!Flask默认在返回302重定向但没让测试客户端跟随的时候,会生成一个非常简陋的默认跳转提示页面,确实不太友好。要自定义这个页面其实有两种实用的方法,咱们一步步来:
方法一:自定义重定向响应类
Flask的redirect函数底层用的是Werkzeug的RedirectResponse,我们可以继承这个类,重写它的get_data方法来替换默认的HTML内容:
from flask import redirect as flask_redirect from werkzeug.wrappers import RedirectResponse # 自定义重定向响应类 class CustomRedirectResponse(RedirectResponse): def get_data(self, as_text=False): # 这里写你想要的自定义HTML模板 custom_html = """ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>访问受限</title> <meta http-equiv="refresh" content="2; url={target}"> <style> body {{ font-family: Arial, sans-serif; text-align: center; padding-top: 100px; }} .alert {{ background: #f8d7da; padding: 20px; border-radius: 5px; width: 60%; margin: 0 auto; }} </style> </head> <body> <div class="alert"> <h3>您需要登录才能访问此页面</h3> <p>系统将在2秒后自动跳转到登录页...</p> <p>如果没有自动跳转,请<a href="{target}">点击这里</a></p> </div> </body> </html> """.format(target=self.location) # 返回处理后的内容,as_text参数对应测试时的get_data(as_text=True) return custom_html if as_text else custom_html.encode('utf-8') # 替换Flask默认的redirect函数 def redirect(location, code=302, Response=None): return flask_redirect(location, code=code, Response=CustomRedirectResponse)
之后在你的Flask应用里,所有需要重定向的地方都使用这个自定义的redirect函数,比如登录校验失败时:
@app.route('/user/settings') def user_settings(): if not current_user.is_authenticated: # 使用自定义的redirect return redirect('/login') # 正常返回设置页面 return render_template('settings.html')
方法二:用after_request钩子全局拦截
如果你不想修改所有的redirect调用,也可以用Flask的after_request钩子来自动拦截所有302重定向响应,替换它的内容:
@app.after_request def customize_redirect_html(response): # 判断是否是302重定向,且响应体是Flask默认的跳转内容 if response.status_code == 302 and b"You should be redirected automatically" in response.get_data(): custom_html = """ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>请先登录</title> </head> <body> <h1>访问被拒绝</h1> <p>您需要登录后才能查看此页面,<a href="{target}">点击前往登录</a></p> </body> </html> """.format(target=response.location) # 更新响应体和内容长度 response.data = custom_html.encode('utf-8') response.content_length = len(response.data) return response
这个方法的优势是无需改动原有代码,自动处理所有符合条件的302重定向,适合全局统一修改的场景。
测试验证
现在在你的单元测试里,不设置follow_redirects=True时,就能拿到自定义的HTML了:
def test_unauthenticated_settings_access(): # 不跟随重定向 response = client.get('/user/settings') assert response.status_code == 302 # 断言自定义内容存在 assert "您需要登录才能访问此页面" in response.get_data(as_text=True)
这样就解决了测试中默认重定向HTML不符合需求的问题啦~
内容的提问来源于stack exchange,提问作者pmlk
相关产品推荐
相关产品推荐

