-
-
Save miohtama/b93fd1ab11353f86e2da2b484d761358 to your computer and use it in GitHub Desktop.
localized routes in pyramid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Self-contained language aware path routing example for Pyramid.""" | |
from urllib.parse import urlunparse | |
from urllib.parse import urlparse | |
from wsgiref.simple_server import make_server | |
from pyramid.config import Configurator | |
from pyramid.httpexceptions import HTTPFound | |
from pyramid.request import Request | |
from pyramid.response import Response | |
def redirect_to_default_language(request: Request): | |
"""A view that redirects path language-free URLs to the default language URLs. | |
E.g. /greeter/foobar -> /en/greeter/foobar | |
""" | |
default_language = request.registry.settings["default_language"] | |
parts = urlparse(request.url) | |
new_path = "/{}{}".format(default_language, parts.path) | |
new_parts = [parts[0], parts[1], new_path, parts[3], parts[4], parts[5]] | |
language_redirected_url = urlunparse(new_parts) | |
return HTTPFound(language_redirected_url) | |
def add_localized_route(config, name, pattern, factory=None, pregenerator=None, **kw): | |
"""Create path language aware routing paths. | |
Each route will have /{lang}/ prefix added to them. | |
Optionally, if default language is set, we'll create redirect from an URL without language path component to the URL with the language path component. | |
""" | |
orig_factory = factory | |
def wrapper_factory(request): | |
lang = request.matchdict['lang'] | |
# determine if this is a supported lang and convert it to a locale, | |
# likely defaulting to your default language if the requested one is | |
# not supported by your app | |
request.path_lang = lang | |
if orig_factory: | |
return orig_factory(request) | |
orig_pregenerator = pregenerator | |
def wrapper_pregenerator(request, elements, kw): | |
if 'lang' not in kw: | |
# not quite right but figure out how to convert request._LOCALE_ back into a language url | |
kw['lang'] = request.path_lang | |
if orig_pregenerator: | |
return orig_pregenerator(elements, kw) | |
return elements, kw | |
if pattern.startswith('/'): | |
new_pattern = pattern[1:] | |
else: | |
new_pattern = pattern | |
new_pattern = '/{lang}/' + new_pattern | |
# Language-aware URL routed | |
config.add_route(name, new_pattern, factory=wrapper_factory, pregenerator=wrapper_pregenerator, **kw) | |
# Add redirect to the default language routes | |
if config.registry.settings.get("default_language"): | |
# TODO: This works only for the most simplest routes | |
fallback_route_name = name + "_language_redirect_fallback" | |
config.add_route(fallback_route_name, pattern) | |
config.add_view(redirect_to_default_language, route_name=fallback_route_name) | |
def home(request): | |
"""Example of language aware parameterless routing.""" | |
if request.path_lang == "fi": | |
msg = 'Hyvää päivää!' | |
else: | |
msg = 'Hello sir' | |
# This will use current language | |
# and automatically populate /{lang}/ matchdict | |
# as in wrapper_pregenerator() | |
another_url = request.route_url("greeter", name="mikko") | |
text = """{} | |
Also see {} | |
""".format(msg, another_url) | |
return Response(text) | |
def greeter(request): | |
"""Example of language aware matchdict routing.""" | |
name = request.matchdict["name"] | |
if request.path_lang == "fi": | |
return Response('Mitä kuuluu {}?'.format(name)) | |
else: | |
return Response('How are you {}?'.format(name)) | |
if __name__ == '__main__': | |
config = Configurator() | |
# Map all /lang/ free URLs to this language | |
config.registry.settings["default_language"] = "en" | |
# Set up config.add_localized_route | |
config.add_directive('add_localized_route', add_localized_route) | |
# Parameterless routing | |
# This will create | |
# - / | |
# - /fi/ | |
# - /en/ | |
# patterns | |
config.add_localized_route('home', '/') | |
config.add_view(home, route_name='home') | |
# Match dict routing | |
# This will create | |
# - /greet/mikko | |
# - /en/greet/mikko | |
# - /fi/greet/mikko | |
# patterns | |
config.add_localized_route('greeter', '/greet/{name}') | |
config.add_view(greeter, route_name='greeter') | |
# Run the web server | |
app = config.make_wsgi_app() | |
server = make_server('0.0.0.0', 8080, app) | |
server.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment