Fantomas' side - Articles pour le tag middlewarehttps://blog.fantomas.site/blog/tags/middleware/Les derniers articles taggés sous middlewarefrCopyright (c) 2005-2018, Julien FacheSun, 04 May 2014 15:37:27 +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ériencesLe temps des releases : Django-sekh https://blog.fantomas.site/blog/2009/08/31/le-temps-des-releases-django-sekh/ <img src="/media/cache/5a/0b/5a0b1dfc28bb1fa4d28b98d0d50d2208.jpg" alt="Le temps des releases : Django-sekh" /> <p>Vous avez certainement déjà vu dans <strong>Google</strong> quand vous consultez une page depuis son <strong>cache</strong>, les <strong>termes de la recherche sont coloriés</strong> dans le contenu de la page pour permettre de les discerner rapidement.</p><p>De ce principe certains sites ont adapté <strong>la même technique</strong> en coloriant certains mots de la page correspondant à la recherche de l'utilisateur si il provient d'un moteur de recherche.&#160;</p><p>C'est ce que <strong>django-S</strong>earch<strong> E</strong>ngine <strong>K</strong>eywords <strong>H</strong>ighlighter fait ! </p><p>Une fois installé avec <a title="BeautifulSoup" href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a>, il suffit juste d'ajouter ce middleware à la fin de la liste dans votre fichier <strong>settings</strong>.</p><pre>MIDDLEWARE_CLASSES = ( ... 'sekh.middleware.KeywordsHighlightingMiddleware', )</pre><p>Moi quand c'est facile à installer, j'aime ! :D</p><p>Ce middleware va rajouter une balise <strong>span</strong> autour des mots de la recherche, le tout avec des classes qui vont bien permettant la décoration en CSS.</p><p>L'inconvénient est que si votre HTML est mal formatté, le middleware risque de faire planter la page.</p><p>Pour voir <a title="Exemple de django-sekh" href="http://fantomas.willbreak.it/blog/2009/jul/19/release-django-smileys/?hl=django%20middleware">un exemple cliquez ici</a>.</p><p>Pour plus d'informations et pour télécharger le code : </p><p><a title="django-sekh" href="http://github.com/Fantomas42/django-sekh/tree/master">http://github.com/Fantomas42/django-sekh/tree/master</a></p> fantomas42@gmail.com (fantomas)Mon, 31 Aug 2009 18:17:51 +0000https://blog.fantomas.site/blog/2009/08/31/le-temps-des-releases-django-sekh/DéveloppementDjango unique et timed sessions https://blog.fantomas.site/blog/2008/12/24/django-unique-et-timed-sessions/ <img src="/media/cache/7a/e7/7ae7794ebfb995588c172aa4c7bec0af.jpg" alt="Django unique et timed sessions" /> <h1>Comment rendre unique les comptes utilisateurs connectés sur un site en Django ? </h1><p>Ce genre de problématique se retrouve souvent sur les sites internet proposant des abonnements à un service en ligne, voulant empêcher le partage d'abonnement. </p><p>Pour les besoins d'un projet spécifique en Django au sein de la <a href="http://www.emencia.fr" title="Emencia">société Emencia</a> là où je travaille, j'ai du développer un moyen d'empêcher 2 utilisateurs de se connecter sur un compte utilisateur en même temps. </p><p>Mais le problème ne s'arrête pas là, comment empêcher la connection et la déconnection successive entre 2 utilisateurs ? L'idée est de donner un temps minimum de connection à chaque session ouverte pour empêcher la déconnection, par exemple 5 minutes. </p><p>Pour cela j'ai écrit un <strong>Middleware </strong>pour Django qui va se charger de rendre unique chaque sessions utilisateurs sur le site. Utiliser un middleware donne l'avantage d'être réutilisable et facile à installer. </p><pre>MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'utsessions.middleware.UTSessionMiddleware', )</pre><p> Après plusieurs refactorings et tests, permettant de configurer le comportement du middleware, comme la déconnection automatique, j'ai publier le code source sur GoogleCode pour que tout le monde puisse en profiter.</p><p>Pour plus d'informations, ou pour télécharger le code, consulter le site web du projet : <a href="http://code.google.com/p/django-ut-sessions/">Django UT Sessions</a>. </p><p>Pour installer le module depuis Pypi : </p><pre>$ easy_install utsessions</pre> fantomas42@gmail.com (fantomas)Wed, 24 Dec 2008 10:12:22 +0000https://blog.fantomas.site/blog/2008/12/24/django-unique-et-timed-sessions/Développement