<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>2degrees Developers</title>
        <description>This is the development blog by the developers behind 2degrees.</description>
        <link>http://dev.2degreesnetwork.com/</link>
        <atom:link href="http://dev.2degreesnetwork.com/search/label/python" rel="self" type="application/rss+xml" />
        
            
                <item>
                    <title>
                        Looking for Senior/Mid-Level Developers to Change the World!
                    </title>
                    <description>
                        &lt;p&gt;&lt;a href=&quot;http://www.2degreesnetwork.com&quot;&gt;2degrees&lt;/a&gt;, the world’s leading collaboration
platform for sustainable business, are currently looking for disciplined
software developers to build and maintain Python/Django applications.&lt;/p&gt;

&lt;p&gt;We’re fundamentally looking for team players who are able to produce
well-crafted software (e.g., elegant design, self-explanatory code), whether
or not they have prior experience with our stack (which we’d consider a big
plus).&lt;/p&gt;

&lt;p&gt;To learn more about the software that we build, have a look at the Free
Software projects that we host on
&lt;a href=&quot;https://github.com/2degrees&quot;&gt;our GitHub account&lt;/a&gt;. Recent projects include
&lt;a href=&quot;https://github.com/2degrees/hubspot-contacts&quot;&gt;hubspot-contacts&lt;/a&gt; and
&lt;a href=&quot;https://github.com/2degrees/python-recaptcha&quot;&gt;python-recaptcha&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Telecommuting 2-3 days a week is possible, as long as the successful candidates
are able to work in our Oxford office the rest of the time.&lt;/p&gt;

&lt;p&gt;To learn more about these vacancies, head over to
&lt;a href=&quot;https://www.2degreesnetwork.com/about/careers/&quot;&gt;our careers page&lt;/a&gt;.&lt;/p&gt;

                    </description>
                    <pubDate>
                        Fri, 08 May 2015 09:00:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2015/05/senior-midlevel-developers.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2015/05/senior-midlevel-developers.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>
                        Converting our multi-page Django app to use AMD
                    </title>
                    <description>
                        &lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;The application which powers &lt;a href=&quot;https://www.2degreesnetwork.com&quot;&gt;2degrees&lt;/a&gt; has, to date, mainly been driven by a Django-powered back-end. Django is agnostic about any front-end stack and this has certainly contributed to a fairly ad-hoc approach to javascript. With an increasing demand for a more interactive experience, we have been adding more and more javascript, experimenting with &lt;a href=&quot;https://angularjs.org/&quot;&gt;AngularJS&lt;/a&gt; to power our pinboard, and looking at ways to use/build frameworks to play nicely with the back-end. As a result of this work, we have found issues of manageability of the javascript code.&lt;/p&gt;

&lt;h3 id=&quot;manageability-issues&quot;&gt;Manageability issues&lt;/h3&gt;

&lt;p&gt;The issues we had fell into the following categories:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Risk of missing dependencies when inheriting complex pages with lots of javascript.&lt;/li&gt;
  &lt;li&gt;Dependencies loading out-of-order in some cases.&lt;/li&gt;
  &lt;li&gt;The code becoming increasingly complex to manage (poor separation of concerns in the code, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;amd-to-the-rescue&quot;&gt;AMD to the rescue?&lt;/h3&gt;

&lt;p&gt;We hoped that a modular approach to javascript would address all of these issues and more. After some research about various module patterns and loaders, we decided to use &lt;a href=&quot;http://requirejs.org/&quot;&gt;RequireJS&lt;/a&gt;. This decision was based mainly on API features and how well-maintained and well-documented the library is.&lt;/p&gt;

&lt;h2 id=&quot;porting-the-codebase-to-using-requirejs&quot;&gt;Porting the codebase to using RequireJS&lt;/h2&gt;

&lt;p&gt;After performing a spike to asses the complexity of the task, we found that we’d have to carry out the following tasks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Upgrade 3rd party dependencies where AMD wrapped versions are available&lt;/li&gt;
  &lt;li&gt;Add an AMD wrapper to all of our &lt;a href=&quot;https://github.com/2degrees&quot;&gt;open source&lt;/a&gt; javascript libraries&lt;/li&gt;
  &lt;li&gt;Figure out how to deal with non-AMD code (e.g. &lt;a href=&quot;http://google.com/analytics/&quot;&gt;google analytics&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Pass configuration from the back-end to javascript modules in an efficient manner (e.g. URLs for the code to carry out AJAX requests)&lt;/li&gt;
  &lt;li&gt;Pass environmental data to the javascript (e.g. whether the user is authenticated)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;setting-up-the-configuration-file&quot;&gt;Setting up the configuration file&lt;/h3&gt;

&lt;p&gt;After reading the docs on &lt;a href=&quot;http://requirejs.org/docs/api.html#config&quot;&gt;how to configure RequireJS&lt;/a&gt; we decided to alias all our third party modules which live in a &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; directory in our JS folder so that they were available directly rather than as, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;require(['lib/jquery'])&lt;/code&gt;. Not only did we feel this was a nice to have, but neglecting to do this means than no jQuery plugins which support AMD will work, since their AMD wrapper expects jQuery to be available as &lt;code class=&quot;highlighter-rouge&quot;&gt;jquery&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For all the 3rd party libraries which don’t have AMD version available we declared a &lt;a href=&quot;http://requirejs.org/docs/api.html#config-shim&quot;&gt;shim configuration&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;We put out configuration in a separate file which we included in our base template:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{{ JS_MEDIA_URL }}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'async'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/async.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'angular'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/angular.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'domReady'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/domReady.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'jquery'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/jquery-1.11.1.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'jquery.cookie'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/jquery.cookie.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'jquery.form'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/jquery.form.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'jquery.history'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'lib/jquery.history.min'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;shim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'angular'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;deps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'angular'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'jquery.history'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;deps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'jquery'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'History'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;passing-environment-variables-from-django&quot;&gt;Passing environment variables from Django&lt;/h3&gt;

&lt;p&gt;We explored several options for working out how to make some environment data available to the javascript code. We looked at &lt;a href=&quot;http://requirejs.org/docs/api.html#config-moduleconfig&quot;&gt;the document on passing config&lt;/a&gt; but this can only be used on a per-module basis.&lt;/p&gt;

&lt;p&gt;In the end, we took the approach of defining an inline module called &lt;code class=&quot;highlighter-rouge&quot;&gt;env&lt;/code&gt; which we placed in our base Django template:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nx&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'env'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IS_AUTHENTICATED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;is_authenticated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code &lt;em&gt;must&lt;/em&gt; come after the initial loading of the &lt;code class=&quot;highlighter-rouge&quot;&gt;require.js&lt;/code&gt; file. preferably as soon as possible.&lt;/p&gt;

&lt;p&gt;Then inside any modules we need to access the environment, we can do something like:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'env'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'...'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IS_AUTHENTICATED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Do something for authenticated users only&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// more code ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;passing-configuration-to-specific-modules&quot;&gt;Passing configuration to specific modules&lt;/h3&gt;

&lt;p&gt;As mentioned previously, RequireJS provides an excellent feature to configure modules. We took extensive advantage of this to set-up URLs and data from the back-end on a per-module basis, e.g.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nx&quot;&gt;requirejs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'foo/formset'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;max_item_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MAX_FOO_COUNT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'foo/formset'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And in &lt;code class=&quot;highlighter-rouge&quot;&gt;foo/formset.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'module'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'...'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max_item_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;max_item_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// rest of the module&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dealing-with-non-amd-code&quot;&gt;Dealing with non-AMD code&lt;/h3&gt;

&lt;p&gt;There were a couple of examples of 3rd party code which didn’t have AMD support, and it is essentially standalone to support our application. Analytics code is one such example. In this case, we simply used a normal script tag as recommended by the analytics providers.&lt;/p&gt;

&lt;p&gt;One case we came across which didn’t work well with this approach was google maps. After some reading around the best approach we found was to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; plugin for RequireJS:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'async!//maps.google.com/maps/api/js?sensor=false&amp;amp;key={{ GOOGLE_MAPS_API_KEY }}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'use strict'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map_marker_icon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{{ STATIC_IMAGES_URL }}/internal/map_marker.png'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map_shadow_icon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{{ STATIC_IMAGES_URL }}/internal/map_marker_shadow.png'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;uk_latlng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;google&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;LatLng&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;51.776596&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.264314&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// more code ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The switch to AMD was nowhere near as painful as we thought it might have been and the results are already paying dividends in terms of quickly we can develop our javascript code.&lt;/p&gt;

&lt;h3 id=&quot;the-future&quot;&gt;The future&lt;/h3&gt;

&lt;p&gt;We’d love to use the &lt;a href=&quot;http://requirejs.org/docs/optimization.html&quot;&gt;optimizer&lt;/a&gt; but the thought of coupling integrating node.js into our build system for the initial release was unpalatable! We also considered using &lt;a href=&quot;http://bower.io/&quot;&gt;bower&lt;/a&gt; to pull in our 3rd party dependencies, but again time didn’t allow for us to explore this fully.&lt;/p&gt;

                    </description>
                    <pubDate>
                        Fri, 18 Jul 2014 00:00:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2014/07/supporting-amd.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2014/07/supporting-amd.html
                    </guid>
                </item>
            
        
            
        
            
        
            
                <item>
                    <title>
                        Announcing django-pastedeploy-settings: A Maintainable Way to Define Django Settings
                    </title>
                    <description>
                        &lt;p&gt;We’re happy to announce the first beta release of &lt;a href=&quot;http://pythonhosted.org/django-pastedeploy-settings/&quot;&gt;django-pastedeploy-settings&lt;/a&gt;, a more maintainable way to define and override Django settings. Its features include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Simple, Python-free configuration files. The format used is &lt;a href=&quot;http://en.wikipedia.org/wiki/INI_file&quot;&gt;INI&lt;/a&gt; because &lt;a href=&quot;http://stackoverflow.com/a/648262&quot;&gt;configuration files should be declarative, not scripts&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Settings can be inherited. For example, you can define your base settings in your project’s repository, while overriding some from a separate file outside your repository.&lt;/li&gt;
  &lt;li&gt;Setting values are defined with JSON.&lt;/li&gt;
  &lt;li&gt;Variable substitution, allowing you to define a value once and reuse it in different settings.&lt;/li&gt;
  &lt;li&gt;Integration with &lt;a href=&quot;http://www.buildout.org/&quot;&gt;Buildout&lt;/a&gt;, so that you can expose your Django settings to Buildout parts.&lt;/li&gt;
  &lt;li&gt;Integration with &lt;a href=&quot;https://nose.readthedocs.org/en/latest/&quot;&gt;Nose&lt;/a&gt;, so that you can easily set the settings to be used by your test suites.Under the hood, this library uses &lt;a href=&quot;http://pythonpaste.org/deploy/&quot;&gt;Paste Deployment&lt;/a&gt;, a widely-used system which has the sole purpose of enabling developers and sysadmins to configure WSGI applications (like Django) and WSGI servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In spite of this being the first public release of this library, its code is based on &lt;a href=&quot;http://pythonhosted.org/twod.wsgi/&quot;&gt;twod.wsgi&lt;/a&gt; v1, a library which we’ve been maintaining and using in production for over 3 years.&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;You can keep the following file in your project’s repository:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;c&quot;&gt;# base.ini
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[DEFAULT]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;django_settings_module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;your_django_project.settings&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:main]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;egg:django-pastedeploy-settings&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DATABASES&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;&quot;default&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;&quot;ENGINE&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;django.db.backends.sqlite3&quot;,&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;&quot;NAME&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;%(sqlite_db_path)s&quot;,&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And then have two separate files, one for development and the other for production, both of which will extend &lt;i&gt;base.ini&lt;/i&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;c&quot;&gt;# development.ini
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[DEFAULT]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;sqlite_db_path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/dev/your-project.db&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:main]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/your-project-repository/base.ini&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;SECRET_KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;weak key&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DEBUG_PROPAGATE_EXCEPTIONS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;c&quot;&gt;# production.ini
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[DEFAULT]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;sqlite_db_path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/production/your-project.db&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:main]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/your-project-repository/base.ini&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;SECRET_KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;str0ng k3y&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Alternatively, you can keep it all in one file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;c&quot;&gt;# settings.ini
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[DEFAULT]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;django_settings_module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;your_django_project.settings&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:base]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;egg:django-pastedeploy-settings&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DATABASES&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;&quot;default&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;&quot;ENGINE&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;django.db.backends.sqlite3&quot;,&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;&quot;NAME&quot;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;%(sqlite_db_path)s&quot;,&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:development]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;base&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;sqlite_db_path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/dev/your-project.db&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;SECRET_KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;weak key&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;DEBUG_PROPAGATE_EXCEPTIONS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[app:production]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;base&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;sqlite_db_path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/production/your-project.db&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;SECRET_KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;str0ng k3y&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://pypi.python.org/pypi/django-pastedeploy-settings/&quot;&gt;Get it&lt;/a&gt; while it’s hot!&lt;/p&gt;

                    </description>
                    <pubDate>
                        Wed, 19 Jun 2013 13:33:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2013/06/announcing-django-pastedeploy-settings.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2013/06/announcing-django-pastedeploy-settings.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>
                        Making Django play nicely with AngularJS
                    </title>
                    <description>
                        &lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;

&lt;p&gt;During the development of a new feature to allow users to “pin” content to read at a later date, we came up against the age-old problem in our application - how to write javascript without a whole heap of boilerplate. We’ve tried various approaches in the past, e.g. using &lt;a href=&quot;http://handlebarsjs.com/&quot;&gt;Handlebars&lt;/a&gt; to template data received from the server, and wrapping up some repeated operations in some hand-rolled “libraries”. We’d chosen not to use a javascript framework previously since jQuery is a pretty powerful tool which could be used to meet most of our needs since our application consists of many pages which require a small degree of progressive enhancement and not a full-blown client-side application.&lt;/p&gt;

&lt;p&gt;This pinning challenge was a bit different from problems we’d come across before since there would be a pins widget on almost every page in the site and any page that contained our editorial or user-contributed content would be eligible for a pinning control, so we decided that it was the right time to choose a framework, even if it were one with a fairly minimal feature-set for wrapping some low-level operations.&lt;/p&gt;

&lt;h3 id=&quot;why-angularjs&quot;&gt;Why AngularJS?&lt;/h3&gt;

&lt;p&gt;We identified several things which cause us irritation and slow us down when developing javascript and used these as a guide for which library or framework we would use:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A sensible degree of separation of concerns (i.e. model, view, controller type split)&lt;/li&gt;
  &lt;li&gt;Two-way data binding (we were fed up or writing loads of event handlers and updating the DOM all the time when the state changed).&lt;/li&gt;
  &lt;li&gt;Communicating with the server easily.&lt;/li&gt;
  &lt;li&gt;A pure javascript library (we know how to write javascript - we didn’t want to learn another language!)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;separation-of-concerns&quot;&gt;Separation of concerns&lt;/h4&gt;

&lt;p&gt;Taking a look at &lt;a href=&quot;http://todomvc.com/&quot;&gt;TodoMVC&lt;/a&gt;, there were plenty of candidates which satisfied this requirement (after all that’s what TodoMVC is all about!). To be honest, most of these libraries met this requirement fully and the only aspects which swayed us were:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Amount of documentation&lt;/li&gt;
  &lt;li&gt;Size of community (both in terms of development and users)&lt;/li&gt;
  &lt;li&gt;Ease of use of syntax&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;two-way-data-binding&quot;&gt;Two-way data binding&lt;/h4&gt;

&lt;p&gt;Of the libraries surveyed, this feature is available in ones which tend towards the fully-featured framework end of the spectrum, e.g. &lt;a href=&quot;http://emberjs.com/&quot;&gt;ember.js&lt;/a&gt;, &lt;a href=&quot;http://knockoutjs.com/&quot;&gt;knockout.js&lt;/a&gt;, &lt;a href=&quot;http://meteor.com/&quot;&gt;meteor.js&lt;/a&gt; and &lt;a href=&quot;http://angularjs.org/&quot;&gt;angular.js&lt;/a&gt;, or those which simply encapsulate this feature, e.g. &lt;a href=&quot;http://rivetsjs.com/&quot;&gt;rivets.js&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;server-communication&quot;&gt;Server communication&lt;/h4&gt;

&lt;p&gt;Here, there was two camps: those which deal with the communication themselves and those which require the use of, e.g. jQuery. Since this was really only syntactical sugar and we already use jQuery, this feature wasn’t used as a tie-breaker for us.&lt;/p&gt;

&lt;p&gt;The only library that was ruled out here was meteor.js since it relies on a node.js backend and we are constrained by having a Django app powering the backend.&lt;/p&gt;

&lt;h4 id=&quot;language-of-library&quot;&gt;Language of library&lt;/h4&gt;

&lt;p&gt;Nearly all the candidates use javascript to work with them with the exception of &lt;a href=&quot;http://batmanjs.org/&quot;&gt;batman.js&lt;/a&gt; (coffeescript) and the Dart example (which isn’t strictly a library).&lt;/p&gt;

&lt;h4 id=&quot;the-verdict&quot;&gt;The verdict&lt;/h4&gt;

&lt;p&gt;With all of these things in mind we came to the conclusion that we would either have to put a whole load of libraries together or pick one of the fully-featured frameworks. We opted for the latter option on the basis that we’d only have one set of documentation to read and we could guarantee that everything would play nicely together. This got us down to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://emberjs.com/&quot;&gt;ember.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://knockoutjs.com/&quot;&gt;knockout.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://meteor.com/&quot;&gt;meteor.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://angularjs.org/&quot;&gt;angular.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was very little to choose between these in terms of their documentation and syntax and their communities and in the end the decision came down to the fact a couple of us had used angular.js for hobby projects.&lt;/p&gt;

&lt;h3 id=&quot;so-was-angularjs-the-right-choice&quot;&gt;So was angular.js the right choice?&lt;/h3&gt;

&lt;p&gt;In terms of implementation we found angular.js to be an excellent choice in terms of its capabilities. We had some fun with scopes, but learned a great deal. If I had to criticize anything about angular.js, it would be that the documentation is quite variable in quality. Some of it is truly outstanding in terms of worked examples, whereas other parts are very sparse and are written as if the reader is already an expert. That said, there were no points where we thought that we’d made the wrong choice.&lt;/p&gt;

&lt;p&gt;In the end our application came to a couple of hundred lines of javascript and we felt that using a centralized service to co-ordinate the pinning across various widgets led to a good level of abstraction and some easy-to-follow code. We didn’t have to work around anything in angular.js and didn’t need to rely on any third party software to augment the core codebase.&lt;/p&gt;

&lt;h4 id=&quot;was-angularjs-the-right-choice-to-play-nicely-with-django&quot;&gt;Was angular.js the right choice to play nicely with Django?&lt;/h4&gt;

&lt;p&gt;This post isn’t just about the virtues of angular.js, but more about how we found it when coming together with our Django application. By choosing an application framework in javascript to sit on top of an application framework in python led us to feel somewhat nervous. Both Django and angular.js attempt to address many similar aspects of web applications, but their differing domains of operation (server- and client-side respectively) clearly set them apart and we had to be careful to avoid some issues to do with code duplication, etc.&lt;/p&gt;

&lt;h5 id=&quot;routes-vs-urlpatterns&quot;&gt;Routes vs. urlpatterns&lt;/h5&gt;

&lt;p&gt;Angular.js has a &lt;em&gt;routeProvider&lt;/em&gt; service which allows the client to take care of the URL structure and even has an HTML5 mode which would have been appealing to us since we already have our routes defined in the Django application in the form of &lt;em&gt;urlpatterns&lt;/em&gt; in Django’s urls.py system. We initially considered trying to mimic these, but we couldn’t see an easy way to convey the relevant configuration of our app into the client, and we didn’t have much of a need to do so, we didn’t use angular’s &lt;em&gt;routeProvider&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For those whom the &lt;em&gt;routeProvider&lt;/em&gt; would be more relevant, you’re going to need some way of defining URLs in a single place and getting the client and server apps to recognise them!&lt;/p&gt;

&lt;h5 id=&quot;templating&quot;&gt;Templating&lt;/h5&gt;

&lt;p&gt;The syntax of angular.js templates bears a fair amount of similarity to Django’s in the use of the &lt;code class=&quot;highlighter-rouge&quot;&gt;{{ var }}&lt;/code&gt; syntax and we found that we couldn’t mix the two. We could have served the angular templates up as static HTML files via Nginx, but some of the templates needed server-side logic which would have meant duplicating some large parts of logic in the client to avoid this.&lt;/p&gt;

&lt;p&gt;In the end we opted for using the &lt;code class=&quot;highlighter-rouge&quot;&gt;{% verbatim %}&lt;/code&gt; tag in Django to stop it parsing the angular template or by using &lt;code class=&quot;highlighter-rouge&quot;&gt;ng-bind&lt;/code&gt; if we could get away with it. This solution is quite sub-optimal as it means one has to be very careful when considering the boundary of which templating system the file belongs to, but we really needed to use the backend templating system for outputting data (see below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; these issues are not inherent to angular’s templating syntax. We have the same problem with Handlebars templates.&lt;/p&gt;

&lt;h5 id=&quot;data&quot;&gt;Data&lt;/h5&gt;

&lt;p&gt;For a lot of the work we needed to do we were integrating the pinning system in our main content streams and we didn’t have time to re-write everything to use angular as the renderer so we had to mix up blocks of angular template code with that of Django’s (see above). For each piece of content we had a controller instance we needed to know something about the piece of content so that server communications could take place. We ended up injecting variables into data attributes before we began the angular template and then used jQuery to read the data out of the relevant DOM elements. This was pretty unsatisfactory as we had hoped to not have to rely directly on jQuery itself and it seems like a bit of workaround to say the least. However, short of creating a framework to communicate variables between the client and the server (which has a whole load of security considerations) we felt it was the most expedient route to solve the problem.&lt;/p&gt;

&lt;h5 id=&quot;xhr&quot;&gt;XHR&lt;/h5&gt;

&lt;p&gt;By default, angular serializes any POST data as JSON into the body of the request rather than using URL-encoding. This has large advantages when sending complex data-structures as URL-encoding doesn’t really support this without a great deal of effort. However, Django automatically decodes URL-encoded data from the POST to give the view access to key-value pairs of POST variables.&lt;/p&gt;

&lt;p&gt;It is possible to force angular to use URL-encoding but only by encoding the data yourself and passing it to the &lt;em&gt;$http&lt;/em&gt; service as a string. This isn’t a short-coming of either framework, but rather something to watch out for at the interface of the two.&lt;/p&gt;

&lt;h5 id=&quot;csrf&quot;&gt;CSRF&lt;/h5&gt;

&lt;p&gt;For methods other than GET, we use Django’s CSRF protection middleware. Django sets a token in a cookie in the client which needs to be passed back to the server in an HTTP header. We had already altered jQuery’s XHR defaults to include this cookie value as an HTTP header for AJAX requests and we had to duplicate this for angular, but again this is not a failing of the framework, just something to watch for.&lt;/p&gt;

&lt;p&gt;Angular ships with a cookie handling component but this isn’t build into the angular core by default. We already load jquery.cookie so used this rather than angular’s version.&lt;/p&gt;

&lt;h5 id=&quot;so-was-it-right-then&quot;&gt;So was it right then?&lt;/h5&gt;

&lt;p&gt;Bearing in mind the above points, I would have to say yes. I can’t imagine any other framework would have been without issue and we certainly didn’t find anything that was a show-stopper or what we created to be inefficient or a mess.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Angular.js is a great piece of software, but is likely to be one among many other equally good contenders. The framework met all of our needs and was straight-forward to integrate with Django. That said, we didn’t leverage many of the features of Django (our backend code was only a few hundred lines) and it will be interesting to see what happens in the future. It would be great to have a RESTful API (using something like django-rest-framework or similar) and really see what angular.js can do with it’s &lt;em&gt;resourceProvider&lt;/em&gt; service.&lt;/p&gt;

                    </description>
                    <pubDate>
                        Thu, 09 May 2013 13:42:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2013/05/making-django-play-nicely-with-angularjs.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2013/05/making-django-play-nicely-with-angularjs.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>
                        Announcing WSGI X-Sendfile: High-Performance File Transfer for Python/WSGI Applications
                    </title>
                    <description>
                        &lt;p&gt;I’m pleased to announce the first public release of &lt;a href=&quot;http://pythonhosted.org/xsendfile/&quot;&gt;WSGI X-Sendfile&lt;/a&gt;, a library that lets your Python/WSGI application serve static files via your Web server.&lt;/p&gt;

&lt;p&gt;Modern Web servers like Nginx are generally able to serve files faster, more efficiently and more reliably than any Web application they host. These servers are also able to send to the client a file on disk as specified by the Web applications they host. This feature is commonly known as &lt;em&gt;X-Sendfile&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This simple library makes it easy for any WSGI application to use &lt;em&gt;X-Sendfile&lt;/em&gt;, so that they can control whether a file can be served or what else to do when a file is served, without writing server-specific extensions. Use cases include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Restrict document downloads to authenticated users.&lt;/li&gt;
  &lt;li&gt;Log who’s downloaded a file.&lt;/li&gt;
  &lt;li&gt;Force a file to be downloaded instead of rendered by the browser, or serve it with a name different from the one on disk, by setting the Content-Disposition header.This code has been used in production for three years in our Django application, but is now being released as beta in case there are bugs that haven’t become evident in our systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://pypi.python.org/pypi/xsendfile&quot;&gt;Get it&lt;/a&gt; while it’s hot!&lt;/p&gt;

                    </description>
                    <pubDate>
                        Thu, 11 Apr 2013 12:50:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2013/04/announcing-wsgi-x-sendfile-high.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2013/04/announcing-wsgi-x-sendfile-high.html
                    </guid>
                </item>
            
        
            
        
            
                <item>
                    <title>
                        Integrating reCAPTCHA
                    </title>
                    <description>
                        &lt;p&gt;Recently we’ve been looking into using &lt;a href=&quot;http://www.google.com/recaptcha&quot;&gt;reCAPTCHA&lt;/a&gt; for a form on the &lt;a href=&quot;http://www.2degreesnetwork.com/&quot;&gt;2degrees site&lt;/a&gt;. We took a look at the python libraries out there and found that they either didn’t meet our requirements or weren’t sufficiently documented to allow a quick integration with our software.&lt;/p&gt;

&lt;p&gt;So, we’ve developed a couple of open-source libraries to allow easy communication with the reCAPTCHA service:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/2degrees/python-recaptcha&quot;&gt;python-recaptcha&lt;/a&gt; is an alternative to the client that google suggest. We’ve created a fully-tested and well-documented alternative which allows access to the whole API. The main advantage here, is the ability to access the different themes on offer.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/2degrees/django-recaptcha-field&quot;&gt;django-recaptcha-field&lt;/a&gt; is a small library which contains a factory for generating a Django form with a reCAPTCHA field in. All the other libraries we found worked around passing the client IP address to the reCAPTCHA service. Given that the API documentation states that this is a mandatory field, we’ve ensured that this is sent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any suggestions for future improvement in these libraries, we’d love to hear from you. Of course, if you’d like to make the changes yourself you can always fork the libraries on &lt;a href=&quot;https://github.com/2degrees/&quot;&gt;github&lt;/a&gt;!&lt;/p&gt;

                    </description>
                    <pubDate>
                        Thu, 30 Aug 2012 12:54:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2012/08/integrating-recaptcha.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2012/08/integrating-recaptcha.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>
                        Agile team seeks talented Software Developer
                    </title>
                    <description>
                        &lt;p&gt;Are you a recent Software Engineering graduate looking to join an Agile team? Or do you have 3 years industry experience and a passion for learning?&lt;/p&gt;

&lt;p&gt;We’re a fast-paced, well-funded Web 2.0 business looking for a pro-active software developer to join our talented, self-organizing software development team.&lt;/p&gt;

&lt;h3 id=&quot;about-you&quot;&gt;About you&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;You are hungry to learn:&lt;/strong&gt; You actively seek change — always looking for opportunities to improve professionally, and to help your team develop. You read software-related publications, welcome criticism of your work and offer your colleagues honest feedback.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;You’re willing to try new things:&lt;/strong&gt; Want to try your hand at requirements gathering or UI design? If the idea of becoming a &lt;a href=&quot;http://www.agilemodeling.com/essays/generalizingSpecialists.htm&quot;&gt;Generalizing Specialist&lt;/a&gt; appeals, this could be the right job for you.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;You have excellent communication skills:&lt;/strong&gt; You’re comfortable communicating verbally, graphically or in written text, and you’re happy explaining technical concepts to   non-technical people.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;You’re qualified and/or experienced:&lt;/strong&gt; You have a Software Engineering degree, an equivalent certificate from a leading organization (e.g.: &lt;a href=&quot;http://www.computer.org/&quot;&gt;IEEE-CS&lt;/a&gt;, &lt;a href=&quot;http://www.bcs.org/&quot;&gt;BCS&lt;/a&gt;) or have at least 3 years experience.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;You appreciate a sociable, friendly and supportive working environment:&lt;/strong&gt; We value technical expertise and encourage developers to exercise their initiative and engage with the business as a whole.This is primarily a Web Development role. Experience or knowledge of Python, Django, GNU/Linux, Git, jQuery, Solr, Postgres and Agile development methodologies&amp;lt;/b&amp;gt; is a big plus, but is not required. &lt;strong&gt;We simply want someone with the right attitude&lt;/strong&gt; and we’ll help you get up to speed with anything you’re not familiar with!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;about-2degrees&quot;&gt;About 2degrees&lt;/h3&gt;

&lt;p&gt;2degrees is the world leading online community for sustainability professionals. We aim to help businesses accelerate their implementation of sustainability and carbon reduction strategies on a global scale.&lt;/p&gt;

&lt;p&gt;With offices in Oxford, UK and New York City, we work with leading companies including HSBC, Coca-Cola, BASF, Sony, Marks &amp;amp; Spencer, BP, Shell, Eurostar, Sainsbury’s, Hewlett Packard and Royal Mail.&lt;/p&gt;

&lt;p&gt;Working for 2degrees, you’ll enjoy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A nice office in a great location in Oxford, full of people who are free to be themselves.&lt;/li&gt;
  &lt;li&gt;Managers and business people who appreciate technical staff.&lt;/li&gt;
  &lt;li&gt;Support in your continuing professional development.&lt;/li&gt;
  &lt;li&gt;A competitive salary (dependent upon experience).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;about-the-software-development-team&quot;&gt;About the Software Development Team&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;We’re in the process of adopting Scrum and have successfully embedded Agile techniques such as Pair Programming, Test-Driven Development and daily stand up meetings.&lt;/li&gt;
  &lt;li&gt;We contribute to the Free Software we use and publish our own on &lt;a href=&quot;https://github.com/2degrees&quot;&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Our recent and current projects include surfacing popular content,  simplification of our sign-up process, generation of business reports on site usage, and a major rework of content access   permissions which allows us to expose valuable content to non-authenticated users.&lt;/li&gt;
  &lt;li&gt;Future projects include a content recommendation system, integration with the Campaign Monitor mailing service, a re-work of our subscription   model, user tracking and metrics, and major design and UX improvements across the whole site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-to-apply&quot;&gt;How to apply&lt;/h3&gt;

&lt;p&gt;To apply for this role, please &lt;a href=&quot;mailto:gnarea+jobs@tech.2degreesnetwork.com&quot;&gt;send us your CV&lt;/a&gt; and tell us why you think you’re the right person for this job (don’t forget to mention any Free Software contributions you’ve made).&lt;/p&gt;

                    </description>
                    <pubDate>
                        Wed, 17 Aug 2011 15:06:00 +0000
                    </pubDate>
                    <link>
                        http://dev.2degreesnetwork.com/2011/08/agile-team-seeks-talented-software.html
                    </link>
                    <guid isPermaLink="true">
                        http://dev.2degreesnetwork.com/2011/08/agile-team-seeks-talented-software.html
                    </guid>
                </item>
            
        
    </channel>
</rss>
