<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Stefano Apostolico's Blog - tech</title><link href="http://stefanoapostolico.com/" rel="alternate"></link><link href="http://stefanoapostolico.com/feeds/tech.atom.xml" rel="self"></link><id>http://stefanoapostolico.com/</id><updated>2017-10-10T00:00:00+02:00</updated><entry><title>Using multiple serializers with DjangoRestFramework</title><link href="http://stefanoapostolico.com/2017/10/10/drf-multiple-serializers.html" rel="alternate"></link><published>2017-10-10T00:00:00+02:00</published><updated>2017-10-10T00:00:00+02:00</updated><author><name>Stefano Apostolico</name></author><id>tag:stefanoapostolico.com,2017-10-10:/2017/10/10/drf-multiple-serializers.html</id><summary type="html">&lt;p&gt;How to use different serializers with DjangoRestFramework&lt;/p&gt;
</summary><content type="html">&lt;p&gt;How to use different serializers with DjangoRestFramework&lt;/p&gt;

&lt;p&gt;Imagine to have a viewset and you want to parametrize the output,
using different serializers.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;Model&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
    &lt;span class="nv"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;CharField&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;...&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;CharField&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;...&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;CharField&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;...&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;mail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;EmailField&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;...&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;CharField&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;...&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;birthday&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;models&lt;/span&gt;.&lt;span class="nv"&gt;DateField&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;

&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;PersonSerializer&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;HouseSerializer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:    
    &lt;span class="nv"&gt;full_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;serializers&lt;/span&gt;.&lt;span class="nv"&gt;SerializerMethodField&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;

    &lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Meta&lt;/span&gt;:
        &lt;span class="nv"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;House&lt;/span&gt;
        &lt;span class="nv"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;last_name&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;first_name&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;full_name&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;

    &lt;span class="nv"&gt;def&lt;/span&gt; &lt;span class="nv"&gt;get_full_name&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;, &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{0.last_name}, {1.first_name}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;PersonView&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;DynamicSerializerMixin&lt;/span&gt;, &lt;span class="nv"&gt;generics&lt;/span&gt;.&lt;span class="nv"&gt;ListAPIView&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
    &lt;span class="nv"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;House&lt;/span&gt;.&lt;span class="nv"&gt;objects&lt;/span&gt;.&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;
    &lt;span class="nv"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;HouseSerializer&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;it is easy to build a "serializer factory" to build on the fly &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {}

&lt;span class="nv"&gt;def&lt;/span&gt; &lt;span class="nv"&gt;serializer_factory&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt;, &lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ModelSerializer&lt;/span&gt;, &lt;span class="nv"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;None&lt;/span&gt;, &lt;span class="nv"&gt;exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;None&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
    &lt;span class="nv"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;: &lt;span class="nv"&gt;model&lt;/span&gt;}
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;fields&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;None&lt;/span&gt;:
        &lt;span class="nv"&gt;attrs&lt;/span&gt;[&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fields&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fields&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;exclude&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;None&lt;/span&gt;:
        &lt;span class="nv"&gt;attrs&lt;/span&gt;[&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;exclude&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;exclude&lt;/span&gt;

    &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;,&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;hasattr&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Meta&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
        &lt;span class="nv"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;.&lt;span class="nv"&gt;Meta&lt;/span&gt;, &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;Meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Meta&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;, &lt;span class="nv"&gt;parent&lt;/span&gt;, &lt;span class="nv"&gt;attrs&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;model&lt;/span&gt;:
        &lt;span class="nv"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;model&lt;/span&gt;.&lt;span class="nv"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Serializer&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;:
        &lt;span class="nv"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Serializer&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="ss"&gt;)(&lt;/span&gt;&lt;span class="nv"&gt;class_name&lt;/span&gt;, &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;,&lt;span class="ss"&gt;)&lt;/span&gt;, {&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Meta&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;: &lt;span class="nv"&gt;Meta&lt;/span&gt;, }&lt;span class="ss"&gt;)&lt;/span&gt;


&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;DynamicSerializerMixin&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
    &lt;span class="nv"&gt;serializers_fieldsets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;std&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;: &lt;span class="nv"&gt;None&lt;/span&gt;}
    &lt;span class="nv"&gt;serializer_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;ModelSerializer&lt;/span&gt;

    &lt;span class="nv"&gt;def&lt;/span&gt; &lt;span class="nv"&gt;get_serializer_class&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
        &lt;span class="nv"&gt;ser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;.&lt;span class="nv"&gt;request&lt;/span&gt;.&lt;span class="nv"&gt;QUERY_PARAMS&lt;/span&gt;.&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;serializer&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;std&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;ser&lt;/span&gt; &lt;span class="nv"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;cache&lt;/span&gt;:                
            &lt;span class="nv"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;.&lt;span class="nv"&gt;serializers_fieldsets&lt;/span&gt;.&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;ser&lt;/span&gt;, &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;std&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;cache&lt;/span&gt;[&lt;span class="nv"&gt;ser&lt;/span&gt;] &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nv"&gt;serializer_factory&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;.&lt;span class="nv"&gt;model&lt;/span&gt;,
                                  &lt;span class="nv"&gt;self&lt;/span&gt;.&lt;span class="nv"&gt;serializer_class&lt;/span&gt;,
                                  &lt;span class="nv"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;fields&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;cache&lt;/span&gt;[&lt;span class="nv"&gt;ser&lt;/span&gt;]
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;adopt it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;PersonView&lt;/span&gt;(&lt;span class="n"&gt;DynamicSerializerMixin&lt;/span&gt;, &lt;span class="n"&gt;generics&lt;/span&gt;.&lt;span class="n"&gt;ListAPIView&lt;/span&gt;):
    &lt;span class="n"&gt;queryset&lt;/span&gt; = &lt;span class="n"&gt;Person&lt;/span&gt;.&lt;span class="n"&gt;objects&lt;/span&gt;.&lt;span class="nb"&gt;all&lt;/span&gt;()
    &lt;span class="n"&gt;serializer_class&lt;/span&gt; = &lt;span class="n"&gt;PersonSerializer&lt;/span&gt;
    &lt;span class="n"&gt;serializers_fieldsets&lt;/span&gt; = {&lt;span class="s"&gt;'std'&lt;/span&gt;: &lt;span class="n"&gt;PersonSerializer&lt;/span&gt;,
                             &lt;span class="s"&gt;'simple'&lt;/span&gt;: (&lt;span class="s"&gt;'first_name'&lt;/span&gt;, &lt;span class="s"&gt;'last_name'&lt;/span&gt;)
                             }
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;invoke it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;
&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;simpleA&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</content><category term="django"></category><category term="drf"></category><category term="django-rest-framework"></category></entry><entry><title>py.test and Django</title><link href="http://stefanoapostolico.com/2016/11/10/pytest_webtest_django.html" rel="alternate"></link><published>2016-11-10T00:00:00+01:00</published><updated>2016-11-10T00:00:00+01:00</updated><author><name>Stefano Apostolico</name></author><id>tag:stefanoapostolico.com,2016-11-10:/2016/11/10/pytest_webtest_django.html</id><summary type="html">&lt;p&gt;Test django application with py.test and WebTest&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Test django application with py.test and WebTest&lt;/p&gt;

&lt;p&gt;I quit using default Django test suite some years ago, sometimes I go back to it to see if something new can change my mind, but up to now I continue to prefer my choice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://pytest.org/latest/"&gt;py.test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webtest.pythonpaste.org/en/latest/index.html"&gt;WebTest&lt;/a&gt; with &lt;a href="http://pypi.python.org/pypi/django-webtest"&gt;django-webtest&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;Several reasons - here's a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can run unittest, doctest, and nose, style tests suites, making it ideal for new and legacy projects.&lt;/li&gt;
&lt;li&gt;It includes an intuitively named raises context manager for testing exceptions.&lt;/li&gt;
&lt;li&gt;You can define fixture arguments to generate baseline data. This is very, very different from Django-style fixtures.&lt;/li&gt;
&lt;li&gt;Via &lt;code&gt;pytest.ini/setup.cfg&lt;/code&gt; you can change the behavior of pytest.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Integrates nicely with setup.py.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WebTest allows you to model a user's experience much more closely as it is smart about mark-up. Instead of hand-crafting GET and POST requests, you can use the WebTest API to follow links and submit forms - this is what users actually do. As a result, your tests accurately capture user stories.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Writing functional tests with WebTest is both easier and quicker than using Django's test client. It's much simpler to fill in forms that construct complicated arrays of POST data - this is particularly noticable with formsets.&lt;/li&gt;
&lt;li&gt;The WebTest response object supports several ways of parsing the response HTML, making it easy to make complicated assertions about the response.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;response.showbrowser()&lt;/code&gt; is simply amazing&lt;/li&gt;
&lt;/ul&gt;</content><category term="django"></category><category term="pytest"></category></entry><entry><title>False Myths: Customers does not care about technology they care about money</title><link href="http://stefanoapostolico.com/2016/10/26/technology_vs_money.html" rel="alternate"></link><published>2016-10-26T00:00:00+02:00</published><updated>2016-10-26T00:00:00+02:00</updated><author><name>Stefano Apostolico</name></author><id>tag:stefanoapostolico.com,2016-10-26:/2016/10/26/technology_vs_money.html</id><summary type="html"></summary><content type="html">
&lt;p&gt;Yesterday a sentence like this was posted in a collaboration platform:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;"At the end of the day your customers don’t care whether you’re agile, 
lean or practice design thinking."&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I fully agree with the essence of this idea, but it does sounds misleading in one aspect of presentation: This sentence, when interpreted as "customers only care about money", could be a huge mistake. &lt;/p&gt;
&lt;p&gt;Just because our customers do not care how we work, it does not mean that we should not care about methodologies and process.
I don't care what products and tools my dentist uses; it's upto him, but I expect he cares about them a lot!
Tools, processes and metodologies are in our domain and scope - though they do not need to be endorsed by or exposed to our customers,
without an internal professional approach, we cannot deliver great products and services that solve meaningful problems for them in effective ways.&lt;/p&gt;
&lt;p&gt;When the Business/Customer allocates a budget, there's an expectation of return value: a working, reliable product delivered in time and within budget.
If something goes wrong, the Business/Customer complains about money because it is the only "unit of measure" that he/she knows that is understandable in our domain, and is the only common language he/she can speak with us. &lt;/p&gt;
&lt;p&gt;As an analogy, When a new-bought car breaks down after a week, we go back to the vendor and complain &lt;/p&gt;
&lt;p&gt;&lt;em&gt;"Hey, I paid $$$ for this car but it does not work anymore!"&lt;/em&gt;, &lt;/p&gt;
&lt;p&gt;only because we do not know how to say &lt;/p&gt;
&lt;p&gt;&lt;em&gt;"Hey, this car has a design error &lt;xyz&gt;, you should not have sold it!"&lt;/xyz&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ultimately, businesses care about "good products", but the way to deliver 
them cannot pass through a wrong approach or ignoring any methodology only because 
businesses don't care about them "explicitly". &lt;/p&gt;
&lt;p&gt;Again, as an analogy from our experience on flights, I don't think we would expect our planes to be driven overlooking the current best practices, procedures and commonsense, or, even worst, piloted by the first available person.&lt;/p&gt;
&lt;p&gt;Skills, knowledge  and mastering the domain is the only way to give to the 
Business what it expects, any another approach is only a workaroud that 
undermines our reputation and credibility day after day.&lt;/p&gt;</content><category term="methodology"></category><category term="myths"></category></entry><entry><title>About rules, best practices and experience</title><link href="http://stefanoapostolico.com/2015/10/07/rules-best-practices-and-experience.html" rel="alternate"></link><published>2015-10-07T00:00:00+02:00</published><updated>2015-10-07T00:00:00+02:00</updated><author><name>Stefano Apostolico</name></author><id>tag:stefanoapostolico.com,2015-10-07:/2015/10/07/rules-best-practices-and-experience.html</id><summary type="html">&lt;p&gt;What does distinguishes an architect by a good architect, 
a developer from a good developer ?&lt;/p&gt;
</summary><content type="html">&lt;p&gt;What does distinguishes an architect by a good architect, 
a developer from a good developer ?&lt;/p&gt;

&lt;p&gt;Sometimes customers ask me a list of rules or best practices and guidelines 
to adopt in &lt;strong&gt;any&lt;/strong&gt; architecture and/or application.&lt;/p&gt;
&lt;p&gt;Every time, I try to explain that this list does not exist, 
is like create a list of ingredients valid for all the recipes&lt;/p&gt;
&lt;p&gt;If you ask any developer 5 rules to follow to have the perfect code he will 
look at you astonished and reply that there are many "rules" but each time 
the important one is different.&lt;/p&gt;
&lt;p&gt;But if you show a badly written code, good programmer will find the issue and will
be able to explain you why, sometimes simply annotating them as "code smell"&lt;/p&gt;
&lt;p&gt;A good architect is not who apply all the patterns and best practices 
(virtually impossible), a good architect chooses which pattern can ignore and 
which "best practices" can be violated&lt;/p&gt;
&lt;p&gt;Design has nothing related to rules and laws, is judgement, skill, 
knowledge, experience and high capacity for abstraction&lt;/p&gt;</content><category term="it"></category></entry><entry><title>PostGIS, PostgreSQL, and Django on OS X</title><link href="http://stefanoapostolico.com/2015/06/06/osx_postgis_and_django.html" rel="alternate"></link><published>2015-06-06T00:00:00+02:00</published><updated>2015-06-06T00:00:00+02:00</updated><author><name>Stefano Apostolico</name></author><id>tag:stefanoapostolico.com,2015-06-06:/2015/06/06/osx_postgis_and_django.html</id><summary type="html">&lt;p&gt;Here's how I got through the installation and configuration of PostGIS on OS X (10.10 Yosemite).&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Here's how I got through the installation and configuration of PostGIS on OS X (10.10 Yosemite).&lt;/p&gt;

&lt;p&gt;This post is mainly for my reference. I spent too much time to find a clear reproducible way to achieve the result.&lt;/p&gt;
&lt;p&gt;Here's what finally worked for me.&lt;/p&gt;
&lt;h3&gt;The stack&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Postgresql 9.4.3&lt;/li&gt;
&lt;li&gt;PostGIS  2.1.7&lt;/li&gt;
&lt;li&gt;Python 2.7&lt;/li&gt;
&lt;li&gt;Django 1.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Install PostGIS&lt;/h2&gt;
&lt;p&gt;I'm not sure I could have actually accomplished this without Homebrew. It really is a great package management tool for OS X. It handles dependencies with no pain at all.&lt;/p&gt;
&lt;h4&gt;get package info&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;postgis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;this produce something like (partial):  &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;postgis&lt;/span&gt;: &lt;span class="nv"&gt;stable&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;7&lt;/span&gt;, &lt;span class="nv"&gt;HEAD&lt;/span&gt;
&lt;span class="nv"&gt;Adds&lt;/span&gt; &lt;span class="nv"&gt;support&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;geographic&lt;/span&gt; &lt;span class="nv"&gt;objects&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;PostgreSQL&lt;/span&gt;
&lt;span class="nv"&gt;http&lt;/span&gt;:&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nv"&gt;postgis&lt;/span&gt;.&lt;span class="nv"&gt;net&lt;/span&gt;
&lt;span class="nv"&gt;Not&lt;/span&gt; &lt;span class="nv"&gt;installed&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Install PostGIS&lt;/h4&gt;
&lt;p&gt;If the version you got does not match this post, try with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;tap&lt;/span&gt; &lt;span class="n"&gt;postgis&lt;/span&gt;
&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="k"&gt;search&lt;/span&gt; &lt;span class="n"&gt;postgis&lt;/span&gt;
&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;homebrew&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgis20&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;otherwise:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;postgis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Homebrew will install both PostGIS and PostgreSQL, check it with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;
&lt;span class="n"&gt;brew&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;postgis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;the default data dir &lt;code&gt;/usr/local/var/postgres&lt;/code&gt; is owned by &lt;code&gt;root&lt;/code&gt; and I prefre to run my database as non privileged user, first I need to chown the directory&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;chown&lt;/span&gt; &lt;span class="n"&gt;sax&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Initialize&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;initdb&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="n"&gt;utf8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Launch postgres&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;pg_ctl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="k"&gt;start&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To do not receive annoying messages during my daily activities I also create the standard &lt;code&gt;postgres&lt;/code&gt; superuser&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;createuser&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;PostGIS Functions and Template&lt;/h2&gt;
&lt;p&gt;PostGIS essentially is a table a couple of databse views and a many functions. You need to create a "template" database to store all of them.&lt;/p&gt;
&lt;p&gt;Create the database that we use as template for any &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;createdb&lt;/span&gt; &lt;span class="n"&gt;template_postgis&lt;/span&gt;
&lt;span class="n"&gt;psql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgis&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt; &lt;span class="n"&gt;template_postgis&lt;/span&gt;
&lt;span class="n"&gt;psql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgis&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;spatial_ref_sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt; &lt;span class="n"&gt;template_postgis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Create Django database&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;psql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="s1"&gt;'CREATE DATABASE wfp_commonapi_gis;'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;psql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;gis_example&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="s1"&gt;'CREATE EXTENSION postgis;'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;createdb&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="n"&gt;UTF8&lt;/span&gt; &lt;span class="n"&gt;PIPPO&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;template_postgis&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; Do not run django test before you create the "real" PostGIS database (at least with pytest) or you get a &lt;code&gt;OperationalError: FATAL:  database "DBNAME" does not exist&lt;/code&gt;. Seems that Django is not able to create a PostGIS test database if the original one does not exists.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Make PostGIS start automatically&lt;/h2&gt;
&lt;p&gt;This is done following the hint on bottom of &lt;code&gt;brew info postgres&lt;/code&gt; output&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sfv&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;postgresql&lt;/span&gt;&lt;span class="cm"&gt;/*.plist ~/Library/LaunchAgents &lt;/span&gt;
&lt;span class="cm"&gt;launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;Put everything togheter&lt;/h1&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/var/postgres"&lt;/span&gt;
&lt;span class="nv"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/var/postgres/server.log"&lt;/span&gt;

brew install postgis &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
sudo chown sax &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
initdb &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -E utf8  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

pg_ctl -D &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -l &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; start -w &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

createuser -s -r postgres  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

createdb template_postgis &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

psql -f /usr/local/share/postgis/postgis.sql template_postgis  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
psql -f /usr/local/share/postgis/spatial_ref_sys.sql template_postgis  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

pg_ctl status
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</content><category term="django"></category><category term="postgis"></category><category term="postgresql"></category></entry></feed>