<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>Thoughts from Mads Sülau Jørgensen &#187; Django</title> <atom:link href="http://madssj.com/blog/tag/django/feed/" rel="self" type="application/rss+xml" /><link>http://madssj.com/blog</link> <description>Various articles about programming and systems administration.</description> <lastBuildDate>Mon, 27 Jun 2011 08:54:43 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Converting a south 0.7 migration back to 0.6</title><link>http://madssj.com/blog/2010/09/27/converting-a-south-0-7-migration-back-to-0-6/</link> <comments>http://madssj.com/blog/2010/09/27/converting-a-south-0-7-migration-back-to-0-6/#comments</comments> <pubDate>Mon, 27 Sep 2010 13:16:23 +0000</pubDate> <dc:creator>Mads Sülau Jørgensen</dc:creator> <category><![CDATA[Django]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[0.6]]></category> <category><![CDATA[0.7]]></category> <category><![CDATA[convert]]></category> <category><![CDATA[south]]></category> <guid
isPermaLink="false">http://swag.dk/blog/?p=230</guid> <description><![CDATA[I had a minor fight with south earlier today, where someone had created a migration with south 0.7, and I needed it to work with south 0.6. Needless to say that it would be a pain to manually convert it &#8230; <a
href="http://madssj.com/blog/2010/09/27/converting-a-south-0-7-migration-back-to-0-6/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>I had a minor fight with <a
href="http://south.aeracode.org/">south</a> earlier today, where someone had created a migration with south 0.7, and I needed it to work with south 0.6.</p><p>Needless to say that it would be a pain to manually convert it from the better 0.7 format back into 0.6, so I wrote a fairly small python script, that does the job.</p><p><span
id="more-230"></span> Don&#8217;t blame me if the script causes your data to be erased or tables to be dropped. It&#8217;s ment as a guideline, although it worked for me out of the box.</p><p>YMMV.</p><p>Usage: python &lt;south_07to06.py> &lt;path/to/migration.py></p><div
class="wp_syntax"><div
class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
create_table_re = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;db.create_table('([^']+)',&quot;</span><span style="color: black;">&#41;</span>
field_name_re = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;^(s*)('([^']+)', self.gf&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
cur_model = <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #008000;">input</span> = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">input</span>.<span style="color: black;">readlines</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    line = line.<span style="color: black;">rstrip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    match = create_table_re.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;class Migration&quot;</span><span style="color: black;">&#41;</span>:
        line = <span style="color: #483d8b;">&quot;class Migration():&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> line.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;from south.v2&quot;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #483d8b;">'Meta'</span> <span style="color: #ff7700;font-weight:bold;">in</span> line <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #483d8b;">'object_name'</span> <span style="color: #ff7700;font-weight:bold;">in</span> line:
        line = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;(?:, )?'object_name': '[^']+'&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, line<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> cur_model <span style="color: #ff7700;font-weight:bold;">and</span> match:
        cur_model = match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> cur_model <span style="color: #ff7700;font-weight:bold;">and</span> line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'))'</span>:
        cur_model = <span style="color: #008000;">None</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> cur_model:
        field_match = field_name_re.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> field_match:
            spaces = field_match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
            field_name = field_match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
            line = <span style="color: #483d8b;">&quot;%s('%s', orm['%s:%s']), &quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>spaces, field_name, cur_model.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;_&quot;</span>, <span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span>, field_name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> line</pre></div></div> ]]></content:encoded> <wfw:commentRss>http://madssj.com/blog/2010/09/27/converting-a-south-0-7-migration-back-to-0-6/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Django &#8211; sharing a memcached instance</title><link>http://madssj.com/blog/2009/06/23/django-sharing-a-memcached-instance/</link> <comments>http://madssj.com/blog/2009/06/23/django-sharing-a-memcached-instance/#comments</comments> <pubDate>Tue, 23 Jun 2009 11:23:00 +0000</pubDate> <dc:creator>Mads Sülau Jørgensen</dc:creator> <category><![CDATA[Django]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[cache]]></category> <category><![CDATA[memcached]]></category> <category><![CDATA[prefix]]></category> <guid
isPermaLink="false">http://swag.dk/blog/?p=135</guid> <description><![CDATA[Update: Some Curious User brought to my attention, that a ticket has been opened which, when implemented, will add a setting for a cache prefix. It will also allow other cache key manipulations. Django has implemented KEY_PREFIX in the development &#8230; <a
href="http://madssj.com/blog/2009/06/23/django-sharing-a-memcached-instance/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><strong>Update:</strong> <del
datetime="2011-01-04T13:22:30+00:00">Some <a
href="http://swag.dk/blog/2009/06/23/django-sharing-a-memcached-instance/comment-page-1/#comment-812">Curious User</a> brought to my attention, that <a
href="http://code.djangoproject.com/ticket/13795">a ticket</a> has been opened which, when implemented, will add a setting for a cache prefix. It will also allow other cache key manipulations.</del> <del
datetime="2011-03-23T13:04:02+00:00">Django has <a
href="http://docs.djangoproject.com/en/dev/topics/cache/#cache-key-prefixing">implemented</a> <code>KEY_PREFIX</code> in the development version, which currently means, that it will be out in 1.4 iirc.</del> Django 1.3 has <a
href="http://docs.djangoproject.com/en/1.3/topics/cache/#cache-key-prefixing">implemented</a> <code>KEY&#95;PREFIX</code> which solves the problem <i>once and for all</i>.</p><p>Until recently I&#8217;ve been using the <code>file://</code> django cache, but that has a &#8220;problem&#8221; when multiple users needs to manipulate the cache (think uid 80 writes a key, that uid 1000 wants to delete).</p><p>My problem with the <code>memcached://</code> django cache provider has been, that it cannot handle being used on a shared memcached instance, because of the danger of key collissions.</p><p><span
id="more-135"></span> If project A and project B would share a memcached instance, they basiclly share the same global namespace. So if they both write a key called <code>actor</code> there is no telling what will happen.</p><p>So I wrote a little cache backend for django, that uses the current <code>memcached</code> backend, but adds a pre-defined prefix to all keys.</p><p><strong>Usage:</strong> Put the code somewhere inside your project in a file called <code>memcached<em>key</em>prefix.py</code>, and set your <code>CACHE&#95;BACKEND</code> to something like: <code>path.to.memcached&#95;key&#95;prefix:///127.0.0.1:11211/?key<em>prefix=sewc</em>&amp;foo=bar&amp;timeout=3600</code></p><div
class="wp_syntax"><div
class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;Memcached cache backend with key prefixing&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span>.<span style="color: black;">backends</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> InvalidCacheBackendError
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span>.<span style="color: black;">backends</span>.<span style="color: black;">memcached</span> <span style="color: #ff7700;font-weight:bold;">import</span> CacheClass <span style="color: #ff7700;font-weight:bold;">as</span> MemcachedCacheClass
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">encoding</span> <span style="color: #ff7700;font-weight:bold;">import</span> smart_unicode, smart_str
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> CacheClass<span style="color: black;">&#40;</span>MemcachedCacheClass<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, server, params<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #008000;">self</span>._key_prefix = smart_str<span style="color: black;">&#40;</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'key_prefix'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyError</span>:
            <span style="color: #ff7700;font-weight:bold;">raise</span> InvalidCacheBackendError<span style="color: black;">&#40;</span><span style="color: #483d8b;">'key_prefix not specified'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span>server, params<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _get_key<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._key_prefix + smart_str<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, value, timeout=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>, value, timeout<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, default=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>, default<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, value, timeout=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>, value, timeout<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> delete<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">delete</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_many<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, keys<span style="color: black;">&#41;</span>:
        keys = <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> key <span style="color: #ff7700;font-weight:bold;">in</span> keys<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_many</span><span style="color: black;">&#40;</span>keys<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> incr<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, delta=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">incr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>, delta<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> decr<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, delta=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>CacheClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">decr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._get_key<span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>, delta<span style="color: black;">&#41;</span></pre></div></div> ]]></content:encoded> <wfw:commentRss>http://madssj.com/blog/2009/06/23/django-sharing-a-memcached-instance/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>Django compatible PyAMF test client</title><link>http://madssj.com/blog/2009/04/21/django-compatible-pyamf-test-client/</link> <comments>http://madssj.com/blog/2009/04/21/django-compatible-pyamf-test-client/#comments</comments> <pubDate>Tue, 21 Apr 2009 13:18:19 +0000</pubDate> <dc:creator>Mads Sülau Jørgensen</dc:creator> <category><![CDATA[Django]]></category> <category><![CDATA[flash]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[Client]]></category> <category><![CDATA[PyAMF]]></category> <category><![CDATA[Test]]></category> <guid
isPermaLink="false">http://swag.dk/blog/?p=92</guid> <description><![CDATA[While working on a project using PyAMF today, i was about to write a unittest of a service method, when I realized that it would be harder than necessary to make unittests of the service. The cause of this is, &#8230; <a
href="http://madssj.com/blog/2009/04/21/django-compatible-pyamf-test-client/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>While working on a project using <a
href="http://pyamf.org/">PyAMF</a> today, i was about to write a unittest of a service method, when I realized that it would be harder than necessary to make unittests of the service. The cause of this is, that there was no test client wrapper for the django test client for pyamf, which means, that to do a unittest of the gateway, you&#8217;ll have to start a django server, and run a unittest elsewhere.</p><p>Seeing as how there are a lot of benefits to using djangos own test suite (fixtures and automatic database generation to name a few), i set out to write a little test client for PyAMF to utilize django&#8217;s test client, so it would be possible to write a proper test suite.</p><p>This turned out great, and is now <a
href="http://pyamf.org/ticket/508">ticket 508</a> over at PyAMFs trac. Look at the <a
href="http://pyamf.org/attachment/ticket/508/client.py">client.py</a> for the code. At some point, it will be integrated into PyAMF mainline as <code>p.r.c.django.TestClient</code> (or something like that).</p> ]]></content:encoded> <wfw:commentRss>http://madssj.com/blog/2009/04/21/django-compatible-pyamf-test-client/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Fun with mod_macro and django</title><link>http://madssj.com/blog/2008/03/19/fun-with-mod_macro/</link> <comments>http://madssj.com/blog/2008/03/19/fun-with-mod_macro/#comments</comments> <pubDate>Wed, 19 Mar 2008 19:36:06 +0000</pubDate> <dc:creator>Mads Sülau Jørgensen</dc:creator> <category><![CDATA[Apache]]></category> <category><![CDATA[Django]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[Work]]></category> <category><![CDATA[coniuro aps]]></category> <category><![CDATA[mod_macro]]></category> <guid
isPermaLink="false">http://swag.dk/blog/2008/03/19/fun-with-mod_macro/</guid> <description><![CDATA[At work we yestoday decided to update our internal url structure for our client test sites, issue management systems and such arround a bit. Seeing as we decided on purchasing a genuine signed ssl wildcard certificate, we needed to change &#8230; <a
href="http://madssj.com/blog/2008/03/19/fun-with-mod_macro/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>At <a
href="http://www.coniuro.dk/" title="Coniuro ApS - we code">work</a> we yestoday decided to update our internal url structure for our client test sites, issue management systems and such arround a bit. Seeing as we decided on purchasing a genuine signed ssl wildcard certificate, we needed to change our url&#8217;s a bit.</p><p><span
id="more-12"></span></p><p>We used to have a url schema consisting of the following components:</p><pre><code>    [dev.|test.]&lt;project-name&gt;.&lt;client-name&gt;.companyname.tld
</code></pre><p>That made for very long url&#8217;s, and furthermore, the url&#8217;s would not be supported by a <code>*.companyname.tld</code>. Based on this infomation, and wanting to create a more generelized, nicer url schema, we choose to cross over to the following schema:</p><pre><code>   [dev-|test-]&lt;project-name&gt;.companyname.tld
</code></pre><p>Which besides from supporting a wildcard ssl certificate just fine, just, well, looks nicer.</p><p>Either way, me beeing in charge of the contents in <code>/etc/</code>, and getting a little sick of growing apache configuration files, I chooose to write some macros to configure our project sites.</p><p>We generally have 2 types of project sites. <a
href="http://www.djangoproject.com/" title="Django - a python web framework for very rapid development, love it!">django</a> based sites, and PHP based sites.</p><p>A typical django apache configuration consists of a VirtualHost and some mod_python settings inside a Location block. Lot&#8217;s of configuration, very little actual diffrence between the configration projects in between.</p><p>An example of a django based application running inside a apache VirtualHost, could look like this:</p><pre><code>    &lt;VirtualHost *:80&gt;
        ServerName test-project.company.tld
        &lt;Location /&gt;
            SetHandler python-program
            PythonHandler django.core.handlers.modpython
            PythonPath "['/path/to/project', '/other/path/to/inject']"
            SetEnv DJANGO_SETTINGS_MODULE project.settings
        &lt;/Location&gt;
        &lt;Location /media/&gt;
            SetHandler none
        &lt;/Location&gt;
        Alias /media/admin/ /path/to/django/contrib/admin/media/
        Alias /media/ /path/to/project/media/
    &lt;/VirtualHost&gt;
</code></pre><p>And the on top of that comes SSL configuration, auth and such. 25 lines of configuration per django site. Now, I really wanted to acomplish two things.</p><ul><li>Make the configuration easier to maintain</li><li>Enable other users to setup sites without knowing the depths of django and <code>mod_python</code></li></ul><p>Now, apache configuration, meet <a
href="http://www.cri.ensmp.fr/~coelho/mod_macro/" title="mod_macro - a configuration macro module for apache2">mod_macro</a>. The solution to my problem was very simple. Create a macro that handles all the django configuration, given 4 parameters. A server name (i.e. the url), the parent directory of the django site and the module name of the site.</p><p>So i started building my macro.</p><pre><code>    &lt;Macro DjangoSite $servername $root $module&gt;
        &lt;VirtualHost *:80&gt;
            ServerName $servername
            &lt;Location /&gt;
                SetHandler python-program
                PythonHandler django.core.handlers.modpython
                PythonPath "['/common/path/to/inject', '$root']"
                SetEnv DJANGO_SETTINGS_MODULE $modulename.settings
            &lt;/Location&gt;
            &lt;Location /media/&gt;
                SetHandler none
            &lt;/Location&gt;
            Alias /media/admin/ /path/to/django/contrib/admin/media/
            Alias /media/ $root/$module/media/
        &lt;/VirtualHost&gt;
    &lt;/Macro&gt;
</code></pre><p><code>mod_macro</code> is really simple, it will do a longest-match search and replace on the macro&#8217;s content. So, if we had a django site in <code>/path/to/djangosite/testsite/</code> the above macro could be used as:</p><pre><code>    Use DjangoSite www.example.org /path/to/djangosite/ testsite
</code></pre><p>Which would expand to:</p><pre><code>    &lt;VirtualHost *:80&gt;
        ServerName www.example.org
        &lt;Location /&gt;
            SetHandler python-program
            PythonHandler django.core.handlers.modpython
            PythonPath "['/common/path/to/inject', '/path/to/djangosite/']"
            SetEnv DJANGO_SETTINGS_MODULE testsite.settings
        &lt;/Location&gt;
        &lt;Location /media/&gt;
            SetHandler none
        &lt;/Location&gt;
        Alias /media/admin/ /path/to/django/contrib/admin/media/
        Alias /media/ /path/to/djangosite/testsite/media/
    &lt;/VirtualHost&gt;
</code></pre><p>Hope you find this infomation a little useful. I actually like looking at our apache configuration file now.</p> ]]></content:encoded> <wfw:commentRss>http://madssj.com/blog/2008/03/19/fun-with-mod_macro/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
