<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-02-20T06:10:33+00:00</updated><id>/feed.xml</id><title type="html">jaco’s blog</title><subtitle>an experimental blog</subtitle><entry><title type="html">Bye Bye Wing Ide, welcome Visual Studio Code</title><link href="/python/osx/2020/11/29/2020-11-29-bye-bye-wing-ide-wcome-vstudio.html" rel="alternate" type="text/html" title="Bye Bye Wing Ide, welcome Visual Studio Code" /><published>2020-11-29T15:02:00+00:00</published><updated>2020-11-29T15:02:00+00:00</updated><id>/python/osx/2020/11/29/2020-11-29-bye-bye-wing-ide-wcome-vstudio</id><content type="html" xml:base="/python/osx/2020/11/29/2020-11-29-bye-bye-wing-ide-wcome-vstudio.html"><![CDATA[<p>Well, i’m not a big Microsoft fan. And more than this i work on OSX and i love it. So during the last 10 years and more, i always used Wing Ide for my projects. 
Wing IDE is just beatiful, nice, strong and full of features. But i always try improve my tools, my skill and my knowledgement. So recently i gave an opportunity to Visual Studio Code, and at the end i have to admit that is really comfortable.</p>

<p>I like the number of extension available for it. I love pylint, and i love as the UI is designed. More than this the outline, timeline, git integration, compare two file options are really strong features.</p>

<p>Wing has a great number of features and many of the features of Visual Studio are also available in Wing. But i’ve to say that in Visual Studio everything looks like more easy to use and well integrated.</p>

<p>There are a couple of things that make me decide for Visual Studio.</p>

<p>1) First of All is Free
2) It’s open. I can use it also for PHP and more. For example i’m writing this article using an extension for Makdown Language and another one for Jekyll.</p>

<p>So i’ve to say bye bye Wing IDE. Was my favourite editor for a decade, but sometime also a big love has to end.</p>

<p>The only think that was hard with Visual Studio was configure the debugger for django and python. There is a tip that i want share with you. The problem was related to the MySQLdb library. The debugger fail with message <code class="language-plaintext highlighter-rouge">django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module. Did you install mysqlclient?</code> even if MySQLdb it’s installed. The reason is linked to a wrong path inside _mysql.cpython-37-darwin.so.</p>

<p>The only solution i founded was replace the path inside the library as suggested in this <a href="https://stackoverflow.com/a/61211114">stackoverflow article</a></p>

<p>So, bye Wing i loved you, but i fall in love with Visual Studio atm</p>]]></content><author><name></name></author><category term="python" /><category term="osx" /><category term="editor" /><summary type="html"><![CDATA[It's time to change my favourite Python Editor]]></summary></entry><entry><title type="html">AlpineQuest TRK to GPS is out</title><link href="/python/2020/04/19/alpinequest-trk-to-gpx-is-out.html" rel="alternate" type="text/html" title="AlpineQuest TRK to GPS is out" /><published>2020-04-19T17:25:00+00:00</published><updated>2020-04-19T17:25:00+00:00</updated><id>/python/2020/04/19/alpinequest-trk-to-gpx-is-out</id><content type="html" xml:base="/python/2020/04/19/alpinequest-trk-to-gpx-is-out.html"><![CDATA[<p>I’ve just released the 1st beta version of Alp2gpx  simple AlpineQuest Trk2GPX converter</p>

<p>Alpine Quest is a very nice GPS app for outdoor activities
<a href="https://github.com/phkehl/apq2gpx">https://www.alpinequest.net/</a></p>

<p>Alp2Gpx is available at
<a href="https://github.com/jachetto/alp2gpx">https://github.com/jachetto/alp2gpx</a></p>

<p>feel free to fork or collaborate</p>

<p>tnx to Philippe Kehl (phkehl)
<a href="https://github.com/phkehl">https://github.com/phkehl</a></p>

<p>author of 1st apq2gpx converter
<a href="https://github.com/phkehl/apq2gpx">https://github.com/phkehl/apq2gpx</a></p>

<p>Alp2gpx an attemptative to port the original code
developed by Philippe in perl to Python</p>

<p>A special thanks to my friends <strong>‘Amici Alpinisti’</strong>. 
The friends with whom i share my hiking adventures</p>

<p><strong>CHANGELOG</strong></p>
<ul>
  <li>19 April Added support for LDK</li>
  <li>18 April 2020 1st beta release.  Only TRK supported</li>
</ul>]]></content><author><name></name></author><category term="python" /><category term="gpx" /><category term="alpinequest" /><category term="hiking" /><summary type="html"><![CDATA[I’ve just released the 1st beta version of Alp2gpx simple AlpineQuest Trk2GPX converter]]></summary></entry><entry><title type="html">Google API Oauth 2.0 the short way</title><link href="/google/2013/05/31/google-api-oauth-2-dot-0-the-short-way.html" rel="alternate" type="text/html" title="Google API Oauth 2.0 the short way" /><published>2013-05-31T21:24:00+00:00</published><updated>2013-05-31T21:24:00+00:00</updated><id>/google/2013/05/31/google-api-oauth-2-dot-0-the-short-way</id><content type="html" xml:base="/google/2013/05/31/google-api-oauth-2-dot-0-the-short-way.html"><![CDATA[<p>Well 1st of all my problem: more or less one year ago i wrote a nice python script, a shell script that every night downloads datas from my analytics account and save them to a database. It’s useful for my job because i can use this data to better analyze how my business web sites are going.</p>

<p>Now, more or less a week ago my script stopped to work. I had an error 401, limit rate exceeded you need to authenticate…</p>

<p>But my script was authenticated! Yes i used an old gdata api and a normal old ClientLogin API authorization protocol but it worked till last week.</p>

<p>Anyway i decided to switch to the Oauth 2.0 Authentication. There is a ton of documentation about how Oauth 2.0 works and there is a ton of documentation about how a Web Application and a Desktop Application can use Oauth 2.0 to be authenticated with Google API but there is really poor documentation about how a server side script can authenticate itself with google without an human presence.</p>

<!--more-->

<p>So this is my short tutorial.</p>

<ol>
  <li>You need an account on <a href="https://code.google.com/apis/console/?pli=1#project:243201377985">Google API Console</a></li>
  <li>You need a new project</li>
  <li>Click to “API Access” and “Create an OAuth 2.0 Client ID”</li>
  <li>Select “Service Account” and Create Client ID</li>
  <li>“Download Private Key” and save it in a secure place</li>
  <li>Log in in your analytics account and add the email address related to your new project to your analytics property</li>
  <li>Take note of your Client ID</li>
  <li>Install the <a href="http://code.google.com/p/google-api-python-client/">google-api-python-client library</a> to your server</li>
</ol>

<p>We are ready to write code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># getdata.py 
</span><span class="kn">from</span> <span class="nn">apiclient.discovery</span> <span class="kn">import</span> <span class="n">build</span>
<span class="kn">from</span> <span class="nn">oauth2client.file</span> <span class="kn">import</span> <span class="n">Storage</span>
<span class="kn">from</span> <span class="nn">oauth2client.client</span> <span class="kn">import</span> <span class="n">SignedJwtAssertionCredentials</span>
<span class="kn">import</span> <span class="nn">httplib2</span>
<span class="kn">import</span> <span class="nn">os.path</span>

<span class="n">SITE_ROOT</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">realpath</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span>

<span class="n">f</span> <span class="o">=</span> <span class="nb">file</span><span class="p">(</span><span class="s">'%s/%s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">SITE_ROOT</span><span class="p">,</span><span class="s">'PATHTOYOURPRIVATEKEY'</span><span class="p">),</span> <span class="s">'rb'</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">f</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>

<span class="n">http</span> <span class="o">=</span> <span class="n">httplib2</span><span class="p">.</span><span class="n">Http</span><span class="p">()</span>
<span class="n">storage</span> <span class="o">=</span> <span class="n">Storage</span><span class="p">(</span><span class="s">'analytics.dat'</span><span class="p">)</span>
<span class="n">credentials</span> <span class="o">=</span> <span class="n">storage</span><span class="p">.</span><span class="n">get</span><span class="p">()</span>

<span class="k">if</span> <span class="n">credentials</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">or</span> <span class="n">credentials</span><span class="p">.</span><span class="n">invalid</span><span class="p">:</span>
    <span class="n">credentials</span> <span class="o">=</span> <span class="n">SignedJwtAssertionCredentials</span><span class="p">(</span><span class="s">'YOURGSERVICEEMAIL'</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">scope</span><span class="o">=</span><span class="s">'https://www.google.com/analytics/feeds/'</span><span class="p">)</span>        
    <span class="n">storage</span><span class="p">.</span><span class="n">put</span><span class="p">(</span><span class="n">credentials</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">credentials</span><span class="p">.</span><span class="n">refresh</span><span class="p">(</span><span class="n">http</span><span class="p">)</span>
        
<span class="n">http</span> <span class="o">=</span> <span class="n">credentials</span><span class="p">.</span><span class="n">authorize</span><span class="p">(</span><span class="n">http</span><span class="p">)</span>        
<span class="n">service</span> <span class="o">=</span> <span class="n">build</span><span class="p">(</span><span class="n">serviceName</span><span class="o">=</span><span class="s">'analytics'</span><span class="p">,</span> <span class="n">version</span><span class="o">=</span><span class="s">'v3'</span><span class="p">,</span> <span class="n">http</span><span class="o">=</span><span class="n">http</span><span class="p">)</span>
                    
<span class="n">data_query</span> <span class="o">=</span> <span class="n">service</span><span class="p">.</span><span class="n">data</span><span class="p">().</span><span class="n">ga</span><span class="p">().</span><span class="n">get</span><span class="p">(</span>
    <span class="n">ids</span> <span class="o">=</span> <span class="n">table_id</span><span class="p">.</span><span class="n">channel_value</span><span class="p">,</span>
    <span class="n">start_date</span> <span class="o">=</span> <span class="n">date_start</span><span class="p">,</span>
    <span class="n">end_date</span> <span class="o">=</span> <span class="n">date_end</span><span class="p">,</span>
    <span class="n">metrics</span> <span class="o">=</span> <span class="s">'ga:pageviews,ga:visitors'</span><span class="p">,</span>
    <span class="n">sort</span> <span class="o">=</span> <span class="s">'-ga:pageviews'</span><span class="p">).</span><span class="n">execute</span><span class="p">()</span>        

<span class="n">query</span> <span class="o">=</span> <span class="n">data_query</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'totalsForAllResults'</span><span class="p">)</span>
                    
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">query</span><span class="p">.</span><span class="n">iteritems</span><span class="p">():</span>
        	<span class="k">print</span> <span class="s">'%s: %s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="n">value</span><span class="p">)</span>
</code></pre></div></div>

<p>You are done. I won’t speak about the theory of how oauth works, this is a short tutorial. If you want you can learn more at <a href="https://developers.google.com/accounts/docs/OAuth2">https://developers.google.com/accounts/docs/OAuth2</a></p>]]></content><author><name></name></author><category term="google" /><category term="api" /><summary type="html"><![CDATA[Well 1st of all my problem: more or less one year ago i wrote a nice python script, a shell script that every night downloads datas from my analytics account and save them to a database. It’s useful for my job because i can use this data to better analyze how my business web sites are going.]]></summary></entry><entry><title type="html">Applescript Viscosity and the lazy ssh connections</title><link href="/osx/2013/05/23/applescript-viscosity-and-the-lazy-ssh-connections.html" rel="alternate" type="text/html" title="Applescript Viscosity and the lazy ssh connections" /><published>2013-05-23T00:48:00+00:00</published><updated>2013-05-23T00:48:00+00:00</updated><id>/osx/2013/05/23/applescript-viscosity-and-the-lazy-ssh-connections</id><content type="html" xml:base="/osx/2013/05/23/applescript-viscosity-and-the-lazy-ssh-connections.html"><![CDATA[<p>Well , 1st of all: i’m lazy, i’m really a lazy man, so lazy that i’m a developer. And i’m a developer because i can automate most of my jobs.</p>

<p>Now, the picture is i’ve to manage a couple of servers using ssh. Till now nothing of really hard, yes i’ve to use my keyboard and write something like “ssh bla bla bla”. It’s an hard job but i can do it.</p>

<p>Problem: my servers work behind a vpn. So i have to open my vpn client and i’ve to connect to the vpn server, after this i can start to type “ssh bla bla bla”.</p>

<p>Ok i’ve viscosity, it’s a really nice vpn client, and it need just a couple of clicks to connect my vpn server, but it’s too much for me!!!
I can’t survive to the effort.</p>

<p>So i have wrote this little applescript code:</p>

<div class="language-applescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># bin/gotoserver.scpt</span><span class="w">
</span><span class="k">tell</span><span class="w"> </span><span class="nb">application</span><span class="w"> </span><span class="s2">"Viscosity"</span><span class="w">
	</span><span class="k">set</span><span class="w"> </span><span class="nv">connectionState</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="s2">"dunno"</span><span class="w">
	</span><span class="k">repeat</span><span class="w"> </span><span class="k">until</span><span class="w"> </span><span class="p">(</span><span class="nv">connectionState</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Connected"</span><span class="p">)</span><span class="w">
		</span><span class="k">if</span><span class="w"> </span><span class="nv">connectionState</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Disconnected"</span><span class="w"> </span><span class="k">then</span><span class="w">
			</span><span class="nv">connect</span><span class="w"> </span><span class="s2">"nameofyourviscosityconnection"</span><span class="w">
		</span><span class="k">end</span><span class="w"> </span><span class="k">if</span><span class="w">
		</span><span class="k">set</span><span class="w"> </span><span class="nv">connectionState</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="na">state</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nv">connections</span><span class="w"> </span><span class="nb">where</span><span class="w"> </span><span class="na">name</span><span class="w"> </span><span class="ow">is equal</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="s2">"nameofyourviscosityconnection"</span><span class="w">
		</span><span class="k">set</span><span class="w"> </span><span class="nv">connectionState</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="nv">connectionState</span><span class="w"> </span><span class="k">as </span><span class="nc">string</span><span class="w">
	</span><span class="k">end</span><span class="w"> </span><span class="k">repeat</span><span class="w">
	</span><span class="k">tell</span><span class="w"> </span><span class="nb">application</span><span class="w"> </span><span class="s2">"Terminal"</span><span class="w">
		</span><span class="nb">activate</span><span class="w">
		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">count</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nb">windows</span><span class="p">)</span><span class="w"> </span><span class="ow">is</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">then</span><span class="w">
			</span><span class="nv">do</span><span class="w"> </span><span class="nv">script</span><span class="w"> </span><span class="s2">"ssh bla bla vla"</span><span class="w">
		</span><span class="k">else</span><span class="w">
			</span><span class="c1">-- tell application "System Events" to tell process "Terminal" to keystroke "t" using command down</span><span class="w">
			</span><span class="nv">do</span><span class="w"> </span><span class="nv">script</span><span class="w"> </span><span class="s2">"ssh bla bla bla"</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="na">window</span><span class="w"> </span><span class="mi">1</span><span class="w">
		</span><span class="k">end</span><span class="w"> </span><span class="k">if</span><span class="w">
	</span><span class="k">end</span><span class="w"> </span><span class="k">tell</span><span class="w">
</span><span class="k">end</span><span class="w"> </span><span class="k">tell</span><span class="w">
</span></code></pre></div></div>

<p>Looks like easy enough :-) yes you have to substitute “nameofyourviscosityconnection” with the name of your viscosity connection and “bla bla bla”
 with your vpn ip, but i’m sure that you can do it.</p>

<p>The script is self explanatory, it checks if your vpn is connected, if no it open a connection. If a terminal window is open the script use it to run an ssh command, if not, it open a terminal window and run the ssh command.</p>

<p>now, you can open your ~/.bash_profile and add an alias</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># ~/.bash_profile lang:bash</span>
<span class="nb">alias </span><span class="nv">goserver</span><span class="o">=</span><span class="s2">"osascript ~/bin/gotoserver.scpt"</span>
</code></pre></div></div>

<p>and this is all.</p>

<p>Next time, you have to write in your terminal “goservergo” and you will be connected.</p>]]></content><author><name></name></author><category term="osx" /><category term="script" /><category term="vpn" /><category term="viscosity" /><summary type="html"><![CDATA[Well , 1st of all: i’m lazy, i’m really a lazy man, so lazy that i’m a developer. And i’m a developer because i can automate most of my jobs.]]></summary></entry><entry><title type="html">nginx uwsgi django memcache the magic combo</title><link href="/nginx/django/2013/04/08/nginx-uwsgi-django-memcached-the-magic-combo.html" rel="alternate" type="text/html" title="nginx uwsgi django memcache the magic combo" /><published>2013-04-08T16:51:00+00:00</published><updated>2013-04-08T16:51:00+00:00</updated><id>/nginx/django/2013/04/08/nginx-uwsgi-django-memcached-the-magic-combo</id><content type="html" xml:base="/nginx/django/2013/04/08/nginx-uwsgi-django-memcached-the-magic-combo.html"><![CDATA[<p>Well, one of the most interesting feature in Django, is the cache framework. Every django developer use the django cache to speed up the performance.
On the other side, Nginx it’s probably the fastest server for the static file management.
Finally, in this story, we have also uwsgi and memcache, an application server really strong and a memory storage really fast.</p>

<p>Now, a classic deploy could be:</p>

<ul>
  <li>nginx as reverse-proxy and to handle static file</li>
  <li>uwsgi as application server</li>
  <li>django as framework and cache management</li>
  <li>memcache as cache storage</li>
</ul>

<p>So every request is handled by django. The chain is nginx - uwsgi - django - if the page is in memcache serve it from the cache, if not, exec a django view or something.</p>

<p>Our goal is another chain:</p>

<ul>
  <li>nginx as reverse-proxy</li>
  <li>nginx to handle “every request if in cache”</li>
  <li>nginx to handle static file</li>
  <li>uwsgi as application server</li>
  <li>django only as cache writer</li>
  <li>memcahce as cache storage</li>
</ul>

<p>So, let’s start:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#custom/middleware.py
</span><span class="k">class</span> <span class="nc">NginxMemcacheMiddleWare</span><span class="p">:</span>
    <span class="n">cache_timeout</span> <span class="o">=</span> <span class="n">settings</span><span class="p">.</span><span class="n">CACHE_MIDDLEWARE_SECONDS</span>
    <span class="n">key_prefix</span> <span class="o">=</span> <span class="n">settings</span><span class="p">.</span><span class="n">CACHE_MIDDLEWARE_KEY_PREFIX</span>        
	<span class="n">nginx_cache_prefix</span> <span class="o">==</span> <span class="n">settings</span><span class="p">.</span><span class="n">NGINX_CACHE_PREFIX</span>

    <span class="k">def</span> <span class="nf">_session_accessed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span>
         <span class="k">try</span><span class="p">:</span>
             <span class="k">return</span> <span class="n">request</span><span class="p">.</span><span class="n">session</span><span class="p">.</span><span class="n">accessed</span>
         <span class="k">except</span> <span class="nb">AttributeError</span><span class="p">:</span>
             <span class="k">return</span> <span class="bp">False</span>    

    <span class="k">def</span> <span class="nf">process_response</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">):</span>
        <span class="n">path</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">get_full_path</span><span class="p">()</span>
        
        <span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">GET</span><span class="p">.</span><span class="n">has_key</span><span class="p">(</span><span class="sa">u</span><span class="s">'nocache'</span><span class="p">)</span> <span class="ow">and</span> <span class="n">request</span><span class="p">.</span><span class="n">GET</span><span class="p">[</span><span class="sa">u</span><span class="s">'nocache'</span><span class="p">]</span><span class="o">==</span><span class="s">"$no$cache"</span><span class="p">:</span>
            <span class="n">key</span> <span class="o">=</span> <span class="s">"%s:%s"</span> <span class="o">%</span> <span class="p">(</span><span class="s">'NS'</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
            <span class="n">cache</span><span class="p">.</span><span class="n">delete</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
         
        <span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">!=</span> <span class="s">"GET"</span> <span class="ow">or</span> <span class="n">response</span><span class="p">.</span><span class="n">status_code</span> <span class="o">!=</span> <span class="mi">200</span> <span class="ow">or</span> <span class="p">(</span><span class="n">path</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'/admin'</span><span class="p">)):</span>
            <span class="k">return</span> <span class="n">response</span>

        
        <span class="k">try</span><span class="p">:</span>
            <span class="n">key</span> <span class="o">=</span> <span class="s">"%s:%s"</span> <span class="o">%</span> <span class="p">(</span><span class="n">nginx_cache_prefix</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
            <span class="n">cache</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">response</span><span class="p">.</span><span class="n">content</span><span class="p">,</span><span class="bp">self</span><span class="p">.</span><span class="n">cache_timeout</span><span class="p">)</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="k">pass</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="k">del</span> <span class="n">response</span><span class="p">[</span><span class="s">'Last-Modified'</span><span class="p">]</span>
            <span class="k">del</span> <span class="n">response</span><span class="p">[</span><span class="s">'Expires'</span><span class="p">]</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="k">pass</span>

        <span class="n">response</span><span class="p">[</span><span class="s">'Vary'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'Accept-Encoding'</span>
        
        <span class="k">return</span> <span class="n">response</span>
</code></pre></div></div>

<p>Our settings.py will looks like:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#settings.py
</span><span class="n">MIDDLEWARE_CLASSES</span> <span class="o">=</span> <span class="p">(</span>    
    <span class="s">'django.middleware.common.CommonMiddleware'</span><span class="p">,</span>
    <span class="s">'django.contrib.sessions.middleware.SessionMiddleware'</span><span class="p">,</span>
    <span class="s">'django.middleware.csrf.CsrfViewMiddleware'</span><span class="p">,</span>
    <span class="s">'django.contrib.auth.middleware.AuthenticationMiddleware'</span><span class="p">,</span>
    <span class="s">'django.contrib.messages.middleware.MessageMiddleware'</span><span class="p">,</span>
    <span class="s">'custom.middleware.NginxMemcacheMiddleWare'</span><span class="p">,</span>
<span class="p">)</span>
</code></pre></div></div>

<p>And nginx site-enabled configuration:</p>

<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># site_enabled/default.conf</span>
<span class="k">location</span> <span class="n">/</span> <span class="p">{</span>
    <span class="kn">expires</span>       <span class="s">-1</span><span class="p">;</span>
    <span class="kn">add_header</span>    <span class="s">Cache-Control</span> <span class="s">no-cache</span><span class="p">;</span>
    <span class="kn">add_header</span>    <span class="s">Vary</span> <span class="s">User-Agent</span><span class="p">;</span>
    <span class="kn">include</span>     <span class="n">/etc/nginx/uwsgi_params</span><span class="p">;</span>
    <span class="kn">if</span> <span class="s">(</span><span class="nv">$request_method</span> <span class="p">=</span> <span class="s">POST)</span> <span class="p">{</span>
                <span class="kn">uwsgi_pass</span>  <span class="s">uwsgicluster</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kn">default_type</span>  <span class="s">"text/html"</span><span class="p">;</span>
    <span class="kn">charset</span> <span class="s">utf-8</span><span class="p">;</span>
    <span class="kn">set</span> <span class="nv">$memcached_key</span> <span class="s">":1:CUSTOMKEY:</span><span class="nv">$request_uri</span><span class="s">"</span><span class="p">;</span>
    <span class="kn">memcached_pass</span> <span class="nf">localhost</span><span class="p">:</span><span class="mi">11211</span><span class="p">;</span>
    <span class="kn">error_page</span> <span class="mi">404</span> <span class="mi">502</span> <span class="p">=</span> <span class="s">@fallback</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">location</span> <span class="s">@fallback</span> <span class="p">{</span>
    <span class="kn">expires</span>       <span class="s">-1</span><span class="p">;</span>
    <span class="kn">add_header</span>    <span class="s">Cache-Control</span> <span class="s">no-cache</span><span class="p">;</span>
    <span class="kn">add_header</span>    <span class="s">Vary</span> <span class="s">User-Agent</span><span class="p">;</span>
    <span class="kn">include</span>     <span class="n">/etc/nginx/uwsgi_params</span><span class="p">;</span>
    <span class="kn">uwsgi_pass</span>  <span class="s">uwsgicluster</span><span class="p">;</span>
    <span class="kn">internal</span><span class="p">;</span> 
<span class="p">}</span>
</code></pre></div></div>

<p>Where CUSTOMKEY è id the same used in settings.py</p>

<p>That’s all</p>]]></content><author><name></name></author><category term="nginx" /><category term="django" /><category term="memcached" /><category term="performance" /><summary type="html"><![CDATA[How to build a perfect deploy with Nginx, Django, Uwsgi, Memcached]]></summary></entry><entry><title type="html">Custom Django auth to login with email</title><link href="/django/2013/04/05/custom-django-auth-to-login-with-email.html" rel="alternate" type="text/html" title="Custom Django auth to login with email" /><published>2013-04-05T14:13:00+00:00</published><updated>2013-04-05T14:13:00+00:00</updated><id>/django/2013/04/05/custom-django-auth-to-login-with-email</id><content type="html" xml:base="/django/2013/04/05/custom-django-auth-to-login-with-email.html"><![CDATA[<p>Someone asked in django irc channel (#django on freenode): how can login using email as user?</p>

<p>In my opinion there is a simple way: write a custom auth backend.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># settings.py
</span><span class="n">AUTHENTICATION_BACKENDS</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">'backend.email-auth.EmailBackend'</span><span class="p">,</span>
    <span class="s">'django.contrib.auth.backends.ModelBackend'</span><span class="p">,</span>
<span class="p">)</span>
</code></pre></div></div>

<p>at this point you can write your custom backend:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># backend/email-auth.py
</span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.contrib.auth.backends</span> <span class="kn">import</span> <span class="n">ModelBackend</span>
<span class="kn">from</span> <span class="nn">django.contrib.auth.models</span> <span class="kn">import</span> <span class="n">User</span>
<span class="kn">import</span> <span class="nn">re</span>

<span class="n">email_re</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span>
    <span class="sa">r</span><span class="s">"(^[-!#$%&amp;'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&amp;'*+/=?^_`{}|~0-9A-Z]+)*"</span>
    <span class="sa">r</span><span class="s">'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'</span>
    <span class="sa">r</span><span class="s">')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$'</span><span class="p">,</span> <span class="n">re</span><span class="p">.</span><span class="n">IGNORECASE</span><span class="p">)</span> 
            

<span class="k">class</span> <span class="nc">BasicBackend</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">get_user</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">User</span><span class="p">.</span><span class="n">objects</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">user_id</span><span class="p">)</span>
        <span class="k">except</span> <span class="n">User</span><span class="p">.</span><span class="n">DoesNotExist</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>

<span class="k">class</span> <span class="nc">EmailBackend</span><span class="p">(</span><span class="n">BasicBackend</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">email_re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">.</span><span class="n">objects</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="n">username</span><span class="p">)</span>
            <span class="k">except</span> <span class="n">User</span><span class="p">.</span><span class="n">DoesNotExist</span><span class="p">:</span>
                <span class="k">return</span> <span class="bp">None</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">.</span><span class="n">objects</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="n">username</span><span class="p">)</span>
            <span class="k">except</span> <span class="n">User</span><span class="p">.</span><span class="n">DoesNotExist</span><span class="p">:</span>
                <span class="k">return</span> <span class="bp">None</span>
        <span class="k">if</span> <span class="n">user</span><span class="p">.</span><span class="n">check_password</span><span class="p">(</span><span class="n">password</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">user</span>

</code></pre></div></div>

<p>thats’all</p>]]></content><author><name></name></author><category term="django" /><category term="auth" /><summary type="html"><![CDATA[Custom Django auth to login with email]]></summary></entry></feed>