Tym razem krótko, choć tym problemem męczyłem się dłuższy czas (usprawiedliwiam się tylko tym, że siedziałem nad tym w godzinach nocnych i oczywiste rzeczy nie były wtedy dla mnie oczywiste).
Problem: Aplikacja pylonsowa ma działać częściowo w subdomenie (subdomena.naszadomena.com). Subdomena jest tworzona po logowaniu użytkownika z jakiegoś parametru, np. z jego loginu. Po wylogowaniu aplikacja ma działać w domenie podstawowej. Oczywiście trzeba przy tym zachować ciągłość sesji.
Rozwiązanie: Całkiem proste. W pliku .ini, który służy do uruchamiania aplikacji tworzymy zmienną base_domain w sekcji app:main:
base_domain = naszadomena.com
Będzie ona dostępna w słowniku konfiguracji aplikacji request.envir['paste.config']['app_config']['base_domain']. Definiujemy tą zmienną, aby prościej ustalić bazową domenę aplikacji.
W konfiguracji routingu włączamy obsługę subdomen:
def make_map(global_conf={}, app_conf={}):
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
map = Mapper(directory=os.path.join(root_path, 'controllers'))
map.sub_domains = True # tu włączamy obsługę subdomen
UWAGA. Routes domyślnie obsługują domeny w prostym schemacie: domena.koncowka. Jeśli chcemy umieścić domenę pod bardziej fikuśnym adresem, musimy zmienić atrybut .domain_match obiektu routes.base.mapper (czyli obiekt Mapper w aplikacja/config/routing.py). Atrybut zawiera wyrażenie regularne wyciągające domenę podstawową z HTTP_HOST.
W kontrolerze bazowym w aplikacja/base/base.py dopisujemy w BaseController.__before__:
if session.is_new:
session.cookie[session.key]['domain'] = '.%s'%request.environ['paste.config']['app_conf']['base_domain']
session.cookie[session.key]['path']= '/'
session.request['cookie_out'] = session.cookie[session.key].output(header='')
czyli: do nowotworzonego ciasteczka z session id dopisujemy atrybut domain z wartością .naszadomena.com i ścieżką ustawioną na / oraz regenerujemy nagłówek z ciasteczkiem. Nagłówek HTTP będzie wysyłany tylko przy tworzeniu nowej sesji.
W kodzie kontrolera, jeśli chcemy przekierować użytkownika do subdomeny, robimy oczywiście:
redirect_to(h.url_for(subdomain = 'subdomena'))
a kiedy chcemy powrócić do domeny bazowej, ustalamy parametr subdomain na None:
redirect_to(h.url_for(subdomain = None))
Voila!
