Fantomas' side - Entries for the tag templateshttps://blog.fantomas.site/blog/tags/templates/The last entries tagged with templatesfrCopyright (c) 2005-2018, Julien FacheMon, 14 Mar 2011 11:12:15 +0000Ô middleware, mon beau middleware : Request Template Loader https://blog.fantomas.site/blog/2011/03/08/o-middleware-mon-beau-middleware-request-template-loader/ <img src="/media/cache/74/59/74593d216dc7558383bf9189981a97cf.jpg" alt="Ô middleware, mon beau middleware : Request Template Loader" /> <p>Dans le monde du web, là où tout est anarchie (ou presque), je me retrouve confronté assez souvent à cette problématique : </p><blockquote><p>Comment afficher le contenu d'un site réalisé avec Django sur un autre site déjà existant ?</p></blockquote><p>Là où je bosse, on aime bien les <a title="Les balises IFRAME" href="http://www.w3.org/TR/html4/present/frames.html#h-16.5">iframes HTML</a> (no comments please :)), mais le contenu ou le style de la frame incluse ne correspondent pas forcément au site recevant la frame. L'idée, vu qu'on se trouve à la base dans un environnement <a title="Le projet Django" href="http://www.djangoproject.com/">Django</a>, serait de déployer un nouveau site, avec son propre jeu de templates prévues pour le site incluant les frames.</p><p>Mais ce genre de technique nécessite de mettre en place un nouveau domaine, de déployer et de maintenir 2 sites. Bon vous me direz que ce n'est pas forcément ce qu'il y a de plus dur, mais il y a moyen de faire mieux. Et surtout que ce passe-t-il si vous devez faire ce genre d'opération non pas sur 1 site, mais sur plusieurs. Tout de suite cela devient plus ennuyeux. :(</p><p>C'est là où intervient la solution du <a title="Les middlewares sous Django" href="http://docs.djangoproject.com/en/dev/topics/http/middleware/">middleware</a>. L'idée est de pouvoir passer en GET un paramètre qui conditionnera le chargement des templates dans le site source. Comme cela peu importe combien de frames au look différent on devra gérer, la mise en forme et la personnalisation du contenu se fera très facilement.</p><p>Maintenant place au code, les explications sur le fonctionnement viennent directement après.</p><pre>import os from urllib import urlencode from urlparse import urlparse from urlparse import urlunparse try: # For Python &lt; 2.6 from urlparse import parse_qs except ImportError: from cgi import parse_qs from django.conf import settings from django.utils.encoding import smart_str from BeautifulSoup import BeautifulSoup GET_VAR_NAME = getattr(settings, 'TEMPLATE_GET_VAR_NAME', 'from_source') class RequestTemplateMiddleware(object): """Middleware to modify on the fly the loading of the templates""" def __init__(self): self.original_template_dirs = settings.TEMPLATE_DIRS def process_request(self, request): source = request.GET.get(GET_VAR_NAME) if source: settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'templates', source),) + \ settings.TEMPLATE_DIRS return None def process_response(self, request, response): settings.TEMPLATE_DIRS = self.original_template_dirs source = request.GET.get(GET_VAR_NAME) if source and '&lt;html' in response.content: soup = BeautifulSoup(smart_str(response.content)) for link in soup.findAll('a'): link['href'] = self.update_link(link['href'], source) for form in soup.findAll('form'): form['action'] = self.update_link(form['action'], source) form.insert(0, '&lt;div&gt;&lt;input type="hidden" name="%s" ' \ 'value="%s" /&gt;&lt;/div&gt;' % (GET_VAR_NAME, source)) response.content = str(soup) return response def update_link(self, link, source): """Update the links with the good GET parameter""" url_parts = urlparse(link) query_dict = parse_qs(url_parts.query) query_dict.update({GET_VAR_NAME: source}) return urlunparse((url_parts.scheme, url_parts.netloc, url_parts.path, url_parts.params, urlencode(query_dict), url_parts.fragment))</pre><p>Comme on peut le voir, ce middleware va court-circuiter l'ordre de chargement des templates en modifiant la variable <strong>TEMPLATE_DIRS</strong> utilisée par <a title="Chargement des templates sous Django" href="http://docs.djangoproject.com/en/1.2/ref/templates/api/#loader-types">django.template.loaders.filesystem.Loader</a>, grâce à la variable <strong>from_source</strong> passée dans l'url en GET. </p><p>Ensuite il ne reste plus qu'à créer le dossier de templates correspondant à la variable <strong>from_source</strong> et d'y placer les templates personnalisés. A savoir que le nom de la variable passée en GET est configurable pour plus de souplesse. </p><p>La seule dépendance requise est <a title="Documentation de BeautifulSoup" href="http://www.crummy.com/software/BeautifulSoup/documentation.html">BeautifulSoup</a> qui va modifier le contenu HTML afin de pouvoir continuer à utiliser le middleware quand on clique sur un lien ou on valide un formulaire.</p><p>Au delà de l'utilité de ce bout de code, j'espère que cela va vous motiver à programmer et utiliser vos propres middlewares, car cela s'avère souvent la meilleure solution à un problème complexe lors du développement d'un site internet avec Django.</p> fantomas42@gmail.com (fantomas)Tue, 08 Mar 2011 14:38:28 +0000https://blog.fantomas.site/blog/2011/03/08/o-middleware-mon-beau-middleware-request-template-loader/DéveloppementExpériences