python-werkzeug/examples/i18nurls/application.py

94 lines
2.8 KiB
Python

from os import path
from jinja2 import Environment
from jinja2 import PackageLoader
from werkzeug.exceptions import HTTPException
from werkzeug.exceptions import NotFound
from werkzeug.routing import RequestRedirect
from werkzeug.wrappers import Request as BaseRequest
from werkzeug.wrappers import Response as BaseResponse
from .urls import map
TEMPLATES = path.join(path.dirname(__file__), "templates")
views = {}
def expose(name):
"""Register the function as view."""
def wrapped(f):
views[name] = f
return f
return wrapped
class Request(BaseRequest):
def __init__(self, environ, urls):
super().__init__(environ)
self.urls = urls
self.matched_url = None
def url_for(self, endpoint, **args):
if "lang_code" not in args:
args["lang_code"] = self.language
if endpoint == "this":
endpoint = self.matched_url[0]
tmp = self.matched_url[1].copy()
tmp.update(args)
args = tmp
return self.urls.build(endpoint, args)
class Response(BaseResponse):
pass
class TemplateResponse(Response):
jinja_env = Environment(loader=PackageLoader("i18nurls"), autoescape=True)
def __init__(self, template_name, **values):
self.template_name = template_name
self.template_values = values
Response.__init__(self, mimetype="text/html")
def __call__(self, environ, start_response):
req = environ["werkzeug.request"]
values = self.template_values.copy()
values["req"] = req
self.data = self.render_template(self.template_name, values)
return super().__call__(environ, start_response)
def render_template(self, name, values):
template = self.jinja_env.get_template(name)
return template.render(values)
class Application:
def __init__(self):
from i18nurls import views
self.not_found = views.page_not_found
def __call__(self, environ, start_response):
urls = map.bind_to_environ(environ)
req = Request(environ, urls)
try:
endpoint, args = urls.match(req.path)
req.matched_url = (endpoint, args)
if endpoint == "#language_select":
lng = req.accept_languages.best
lng = lng.split("-")[0].lower() if lng else "en"
index_url = urls.build("index", {"lang_code": lng})
resp = Response(f"Moved to {index_url}", status=302)
resp.headers["Location"] = index_url
else:
req.language = args.pop("lang_code", None)
resp = views[endpoint](req, **args)
except NotFound:
resp = self.not_found(req)
except (RequestRedirect, HTTPException) as e:
resp = e
return resp(environ, start_response)