<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Passing Curiosity: Posts tagged application</title>
    <link href="https://passingcuriosity.com/tags/application/application.xml" rel="self" />
    <link href="https://passingcuriosity.com" />
    <id>https://passingcuriosity.com/tags/application/application.xml</id>
    <author>
        <name>Thomas Sutton</name>
        
        <email>me@thomas-sutton.id.au</email>
        
    </author>
    <updated>2010-05-11T00:00:00Z</updated>
    <entry>
    <title>Providing default settings for Django applications</title>
    <link href="https://passingcuriosity.com/2010/default-settings-for-django-applications/" />
    <id>https://passingcuriosity.com/2010/default-settings-for-django-applications/</id>
    <published>2010-05-11T00:00:00Z</published>
    <updated>2010-05-11T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>The problem is a simple one: you’re writing a Django application that needs a
setting or two. You know what they’ll be in the vast majority of cases but you
want to make them configurable, just in case. As you’re a good developer you
live by the maxim: Don’t Repeat Yourself so you’d like to define each of these
values and, for ease of documentation, all of them in one place. Alas, you’re
out of luck: Django does not provide any support for applications to supply
their own default values for settings. Thankfully though, all it takes is a
few lines of code and your application can shoehorn its own default values
into the global settings system.</p>
<p>First, a proviso to what follows: I am almost certain that this is a bad idea
and that you should do it. At the very least, you should make sure that your
setting names don’t clash (I like to prefix them with the app name).</p>
<p>The goal is simple: your app should contain a <code>settings</code> module which defines
the default values for your application’s settings. These values should be
injected into Django’s settings system so that <code>manage.py diffsettings</code> and
similar functionality all work as you’d expect.</p>
<p>The approach is just as simple: add some code to the top-level module of your
application that loops over the values in your <code>app.settings</code> module and
inject them into the <code>django.conf.global_settings</code> module and (because it’s
already been initialised by the time apps are loaded) the
<code>django.conf.settings</code> object (being careful not to stop on actual configured
with your default values).</p>
<p>The code itself is pretty simple. From <code>app/__init__.py</code>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> inject_app_defaults(application):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>	<span class="co">&quot;&quot;&quot;Inject an application's default settings&quot;&quot;&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>	<span class="cf">try</span>:</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>		<span class="bu">__import__</span>(<span class="st">'</span><span class="sc">%s</span><span class="st">.settings'</span> <span class="op">%</span> application)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>		<span class="im">import</span> sys</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>		</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>		<span class="co"># Import our defaults, project defaults, and project settings</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>		_app_settings <span class="op">=</span> sys.modules[<span class="st">'</span><span class="sc">%s</span><span class="st">.settings'</span> <span class="op">%</span> application]</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>		_def_settings <span class="op">=</span> sys.modules[<span class="st">'django.conf.global_settings'</span>]</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>		_settings <span class="op">=</span> sys.modules[<span class="st">'django.conf'</span>].settings</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>		<span class="co"># Add the values from the application.settings module</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>		<span class="cf">for</span> _k <span class="kw">in</span> <span class="bu">dir</span>(_app_settings):</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>			<span class="cf">if</span> _k.isupper():</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>				<span class="co"># Add the value to the default settings module</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>				<span class="bu">setattr</span>(_def_settings, _k, <span class="bu">getattr</span>(_app_settings, _k))</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>				</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>				<span class="co"># Add the value to the settings, if not already present</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>				<span class="cf">if</span> <span class="kw">not</span> <span class="bu">hasattr</span>(_settings, _k):</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>					<span class="bu">setattr</span>(_settings, _k, <span class="bu">getattr</span>(_app_settings, _k))</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>	<span class="cf">except</span> <span class="pp">ImportError</span>:</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>		<span class="co"># Silently skip failing settings modules</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>		<span class="cf">pass</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>inject_app_defaults(<span class="va">__name__</span>)</span></code></pre></div>
<p>You can see the code in a proof of concept application in my
<a href="http://github.com/thsutton/django-application-settings/">django-application-settings</a> project on GitHub.</p>]]></summary>
</entry>

</feed>
