<?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>Furry Brains &#187; python</title>
	<atom:link href="http://furrybrains.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://furrybrains.com</link>
	<description>The Furry Brains blog tackles a wide range of issues related to web development and design.</description>
	<lastBuildDate>Mon, 22 Jun 2009 16:39:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Named Scopes for Django</title>
		<link>http://furrybrains.com/2009/06/22/named-scopes-for-django/</link>
		<comments>http://furrybrains.com/2009/06/22/named-scopes-for-django/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 16:24:10 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=155</guid>
		<description><![CDATA[There are really only a handful of features I miss about Ruby on Rails, having switched over to using only Django about a year ago. One of the biggest among these has been named scopes.
What a named scope does in Rails, in Django terms, is allow you to name a given query and use it [...]]]></description>
			<content:encoded><![CDATA[<p>There are really only a handful of features I miss about Ruby on Rails, having switched over to using only Django about a year ago. One of the biggest among these has been named scopes.</p>
<p>What a <a href="http://www.pathf.com/blogs/2008/06/named-scopes-are-awesome/">named scope</a> does in Rails, in Django terms, is allow you to name a given query and use it as a base, or &#8220;scope,&#8221; for further queries. In other words, your narrowing down the results upon which additional queries that you run will be executed.</p>
<p>It&#8217;s pretty much the same idea behind modifying initial Manager QuerySets <a href="http://docs.djangoproject.com/en/dev/topics/db/managers/#modifying-initial-manager-querysets">as outlined in the Django documentation</a>, with one major difference: Scopes can be chained. Chaining is the feature I had long coveted, and I had been banging my head around for a solution for the last few months.</p>
<p>The other day while I was poking around the internals a bit though, a decent idea came to me. I realized it would be quite simple for me to extend the default <code>Manager</code> class with an attribute where I could store <code>QuerySet</code> methods I wanted to execute as part of a scope, and then overwrite <code>get_query_set()</code> with a hook that ran these methods before executing the rest of the query.</p>
<p>This turned out to be a nice strategy, and with the addition of some decorators the interface itself turned out to be extraordinarily simple.</p>
<p><span id="more-155"></span></p>
<p>Anyhow, here&#8217;s a walkthrough of how my alpha &#8220;scopable&#8221; module would work, with example code.</p>
<p>Let&#8217;s start with a simplistic blog post model:</p>
<pre class="brush: python;">
class Post(models.Model):
    title           = models.CharField('title', max_length=200)
    author          = models.ForeignKey(User)
    body            = models.TextField('author')
    publish_at      = models.DateTimeField('published at', default=datetime.now)
    is_draft        = models.BooleanField('is draft', default=False)
    is_deleted      = models.BooleanField('deleted', default=False)
    objects         = PostManager()
</pre>
<p>That&#8217;s enough to provide for some good example scopes. Now, here&#8217;s what <code>PostManager</code> might look like, with explanation to follow:</p>
<pre class="brush: python;">
from scopable import ScopableManager, scope

class PostManager(ScopableManager):
    @property
    @scope
    def active(self):
       return self.filter(is_deleted=False, user__is_active=True)

    @property
    @scope
    def published(self):
       return self.filter(is_draft=False)

    @property
    @scope
    def public(self):
       return self.active.published
</pre>
<p>So as you can see, the <code>ScopableManager</code> class is very easy to use; you just add the <code>@scope</code> decorator to any method that you want to turn into a scope. (Note that I added the <code>@property</code> decorator as a stylistic preference; it&#8217;s not required.)</p>
<p>To use the code, you just have to be sure to call a QuerySet method after it, e.g.:</p>
<pre class="brush: python;">
Post.objects.active.all()
Post.objects.published.all()
Post.objects.active.published.filter(publish_at__lte=datetime.now())
Post.objects.public.all()
</pre>
<p>The only difference between a scoped and unscoped method is that execution of any <code>QuerySet</code> methods defined in a scoped method are deferred until a <code>QuerySet</code> method is called (e.g. <code>Post.objects.public.all()</code>), and scoped methods return an instance of your manager back, so they can be chained. As you can see from the <code>public</code> method, scoped methods can be nested as well.</p>
<p>Why is this awesome? Well the main advantage from my perspective is that it allows your business rules to be defined in one and only one discrete place.</p>
<p>So if, for example, I added a new business rule that blog posts shouldn&#8217;t be considered published unless they were not drafts and the publish date had already passed, I could just add that rule to the <code>published</code> method:</p>
<pre class="brush: python;">
    @property
    @scope
    def published(self):
       return self.filter(publish_at__lte=datetime.now(), is_draft=False)
</pre>
<p>This means that any other queries that were built on <code>published</code>, such as <code>public</code>, are now updated with the new business logic we added to <code>published</code>.</p>
<p>The implementation of all of this is pretty straightforward. The main complication comes from implementing scope as a decorator and trying to elegantly capture all of the <code>QuerySet</code> methods used in a scoped <code>Manager</code> method.</p>
<p>This is still alpha code, and as of now it doesn&#8217;t handle custom <code>Manager</code> methods that are not scoped. I mostly just wanted to get this idea out there before I do any more work:</p>
<pre class="brush: python;">
&quot;&quot;&quot;
scopable.py - A module for providing Rails-like named scopes to Django model Managers
Verson 0.1
&quot;&quot;&quot;

from functools import wraps
from django.db import models

class DummyManager(object):
    def __init__(self, actual_mgr, calls=[]):
        super(DummyManager, self).__init__()
        self.actual_mgr = actual_mgr
        self.calls = calls

    def __call__(self, *args, **kwargs):
        last_call = self.calls[-1]
        last_call[&quot;is_property&quot;] = False
        last_call[&quot;args&quot;] = args
        last_call[&quot;kwargs&quot;] = kwargs
        clone = DummyManager(self.actual_mgr, self.calls)
        self.calls = []
        return clone

    def __getattribute__(self, name):
        if name in [&quot;calls&quot;, &quot;actual_mgr&quot;]:
            return super(DummyManager, self).__getattribute__(name)

        # attr_type, args, and kwargs are set here by default in case the attr never gets called
        call = { &quot;attr&quot;: name, &quot;is_property&quot;: True, &quot;args&quot;: [], &quot;kwargs&quot;: {} }

        # if this is a default manager method
        if hasattr(models.Manager, name):
            call[&quot;definition&quot;] = &quot;default&quot;

        # else if this is a custom manager method
        elif hasattr(self.actual_mgr.__class__, name):
            call[&quot;definition&quot;] = &quot;custom&quot;

        # if it can't be found in those two classes, throw an error
        else:
            raise AttributeError(&quot;'%s' object has no attribute '%s'&quot; % (self.actual_mgr.__class__.__name__, name))

        self.calls.append(call)
        clone = DummyManager(self.actual_mgr, self.calls)
        self.calls = []
        return clone

def scope(fn):
    @wraps(fn)
    def scopified(*args, **kwargs):
        args_list = list(args)
        actual_mgr = args_list.pop(0)
        dummy = DummyManager(actual_mgr, [])
        args_list.insert(0, dummy)
        deferred_calls = get_deferred_calls(actual_mgr, fn, args_list, kwargs)
        a = actual_mgr.__class__(deferred_calls=deferred_calls)
        a.contribute_to_class(actual_mgr.model, actual_mgr.model.__name__)
        return a
    return scopified

def get_deferred_calls(mgr, fn, args, kwargs):
    deferred_calls = []
    result = fn(*args, **kwargs)
    if result.calls:
        for call in result.calls:
            if call[&quot;definition&quot;] == &quot;default&quot;:
                deferred_calls.append(call)
            elif call[&quot;definition&quot;] == &quot;custom&quot;:
                next_result = getattr(mgr, call[&quot;attr&quot;])
                if not call[&quot;is_property&quot;]:
                    next_result = next_result(*call[&quot;args&quot;], **call[&quot;kwargs&quot;])
                deferred_calls = deferred_calls + next_result.deferred_calls
            else:
                raise AssertionError(&quot;Something went wrong.&quot;)
    return deferred_calls

class ScopableManager(models.Manager):

    def __init__(self, deferred_calls=[]):
        super(ScopableManager, self).__init__()
        self.scopes = []
        self.deferred_calls = deferred_calls

    def get_query_set(self):
        qs = super(ScopableManager, self).get_query_set()
        if self.deferred_calls:
            for deferred_call in self.deferred_calls:
                next_qs = getattr(qs, deferred_call[&quot;attr&quot;])
                if not deferred_call[&quot;is_property&quot;]:
                    next_qs = next_qs(*deferred_call[&quot;args&quot;], **deferred_call[&quot;kwargs&quot;])
                qs = next_qs
        return qs
</pre>
<p>Please let me know in the comments if you have feedback, suggestions, bugs, grave warnings, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/06/22/named-scopes-for-django/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Prepending an Indefinite Article (a or an) in Front of a Word or Phrase</title>
		<link>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/</link>
		<comments>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 22:29:06 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=126</guid>
		<description><![CDATA[Today, I had to whip up a Django template tag to add &#8220;a&#8221; or &#8220;an&#8221; in front of a phrase.
It started off pretty easy &#8212; just use &#8220;an&#8221; when the first letter of the phrase is a vowel and otherwise use &#8220;a.&#8221; And then I remembered about abbreviations (&#8220;an HR department&#8221;), silent H words (&#8220;an [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I had to whip up a Django template tag to add &#8220;a&#8221; or &#8220;an&#8221; in front of a phrase.</p>
<p>It started off pretty easy &#8212; just use &#8220;an&#8221; when the first letter of the phrase is a vowel and otherwise use &#8220;a.&#8221; And then I remembered about abbreviations (&#8220;an HR department&#8221;), silent H words (&#8220;an honorable man&#8221;), and exceptions among a few O and U words (&#8220;a one-time offer&#8221; or &#8220;a union representative&#8221;), and suddenly it wasn&#8217;t so easy.</p>
<p>Fortunately I managed to find an excellent <a href="http://www.speech.cs.cmu.edu/cgi-bin/cmudict">database of English words that includes pronunciations</a>, and in no time at all I was able to generate a list of exceptions.</p>
<p>Here&#8217;s the final result, implemented as a <a href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/">custom django template tag</a> (in my use case, I needed to able to wrap the original phrase in an HTML tag, so I couldn&#8217;t use a filter tag). This could also easily be a standalone Python function as well (literally by removing the <code>@register.simple_tag</code> decorator).</p>
<p><span id="more-126"></span></p>
<pre class="brush: python;">
import re

@register.simple_tag
def with_indefinite_article(phrase, before_phrase=&quot;&quot;, after_phrase=&quot;&quot;):
    silent_h_words = [&quot;homage&quot;, &quot;hour&quot;, &quot;herb&quot;, &quot;heir&quot;, &quot;honest&quot;, &quot;honor&quot;]
    letters_with_initial_vowel_sound = [&quot;a&quot;, &quot;e&quot;, &quot;f&quot;, &quot;h&quot;, &quot;i&quot;, &quot;l&quot;, &quot;m&quot;, &quot;n&quot;, &quot;o&quot;, &quot;r&quot;, &quot;s&quot;, &quot;x&quot;]
    vowels = [&quot;a&quot;, &quot;e&quot;, &quot;i&quot;, &quot;o&quot;, &quot;u&quot;]
    o_exceptions = [&quot;once&quot;,&quot;one&quot;,&quot;oneness&quot;,&quot;ones&quot;,&quot;oneself&quot;,&quot;onetime&quot;]
    u_exceptions = [&quot;ubiquitous&quot;,&quot;uganda&quot;,&quot;ugandan&quot;,&quot;ukraine&quot;,&quot;ukrainian&quot;,&quot;ukulele&quot;,&quot;ukuleles&quot;,&quot;unanimous&quot;,&quot;unanimously&quot;,&quot;unicellular&quot;,&quot;unicorn&quot;,&quot;unicorns&quot;,&quot;unicycle&quot;,&quot;unicycles&quot;,&quot;unification&quot;,&quot;unified&quot;,&quot;uniform&quot;,&quot;uniformed&quot;,&quot;uniformly&quot;,&quot;uniforms&quot;,&quot;unify&quot;,&quot;unifying&quot;,&quot;unilateral&quot;,&quot;unilateralism&quot;,&quot;unilaterally&quot;,&quot;union&quot;,&quot;unionist&quot;,&quot;unionists&quot;,&quot;unionization&quot;,&quot;unionized&quot;,&quot;unionizing&quot;,&quot;unions&quot;,&quot;unique&quot;,&quot;uniquely&quot;,&quot;uniqueness&quot;,&quot;unisex&quot;,&quot;unison&quot;,&quot;unisons&quot;,&quot;unit&quot;,&quot;unitarian&quot;,&quot;unitary&quot;,&quot;unite&quot;,&quot;united&quot;,&quot;uniting&quot;,&quot;units&quot;,&quot;unity&quot;,&quot;universal&quot;,&quot;universally&quot;,&quot;universe&quot;,&quot;universes&quot;,&quot;universities&quot;,&quot;university&quot;,&quot;universitys&quot;,&quot;unix&quot;,&quot;uranium&quot;,&quot;urinalysis&quot;,&quot;urinary&quot;,&quot;urinate&quot;,&quot;urinating&quot;,&quot;urine&quot;,&quot;urologist&quot;,&quot;urologists&quot;,&quot;urology&quot;,&quot;uruguay&quot;,&quot;uruguayan&quot;,&quot;uruguays&quot;,&quot;usable&quot;,&quot;usage&quot;,&quot;usages&quot;,&quot;use&quot;,&quot;used&quot;,&quot;useful&quot;,&quot;usefully&quot;,&quot;usefulness&quot;,&quot;useless&quot;,&quot;usenet&quot;,&quot;user&quot;,&quot;users&quot;,&quot;uses&quot;,&quot;usual&quot;,&quot;usually&quot;,&quot;usurp&quot;,&quot;usurpation&quot;,&quot;usurped&quot;,&quot;usurper&quot;,&quot;usurping&quot;,&quot;usury&quot;,&quot;utah&quot;,&quot;utahn&quot;,&quot;utahns&quot;,&quot;utahs&quot;,&quot;utensil&quot;,&quot;utensils&quot;,&quot;uterine&quot;,&quot;utero&quot;,&quot;uterus&quot;,&quot;utilitarian&quot;,&quot;utilities&quot;,&quot;utility&quot;,&quot;utilitys&quot;,&quot;utilization&quot;,&quot;utilize&quot;,&quot;utilized&quot;,&quot;utilizes&quot;,&quot;utilizing&quot;,&quot;utopia&quot;,&quot;utopian&quot;,&quot;utopians&quot;,&quot;utopias&quot;]

    # get rid of everything but letters and numbers and a few characters
    first_word = re.sub(r&quot;[^A-Za-z0-9\-]&quot;, &quot;&quot;, phrase.split()[0])
    first_letter = first_word[0].lower()

    # default to 'a'
    article = &quot;a&quot;

    if first_word.isupper() or (len(first_word) == 1):
        # if all caps or a single letter, we're going to assume it's an abbreviation
        if first_letter in letters_with_initial_vowel_sound:
            article = &quot;an&quot;
    elif first_letter == &quot;h&quot; and any( [re.match(r'(?i)%s' % w, first_word) for w in silent_h_words] ):
        article = &quot;an&quot;
    elif first_letter in vowels:
        if first_letter == 'e':
            article = &quot;a&quot; if first_word.lower().split('-')[0] == 'ewe' else &quot;an&quot;
        elif first_letter == 'o':
            article = &quot;a&quot; if first_word.lower().split('-')[0] in o_exceptions else &quot;an&quot;
        elif first_letter == 'u':
            article = &quot;a&quot; if first_word.lower().split('-')[0] in u_exceptions else &quot;an&quot;
        else:
            article = &quot;an&quot;

    return &quot;%s %s%s%s&quot; % (article, before_phrase, phrase, after_phrase)
</pre>
<p>Hopefully this will save someone who stumbles upon this some extra work down the road. If you find any bugs, please let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2009/01/26/with_indefinite_article-a-django-template-tag/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using &#8220;in&#8221; in QuerySets in Django</title>
		<link>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/</link>
		<comments>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 03:11:14 +0000</pubDate>
		<dc:creator>Jim Dalton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[queryset]]></category>

		<guid isPermaLink="false">http://furrybrains.com/?p=85</guid>
		<description><![CDATA[So the purpose of this post is just to look at a neat way of solving a problem in Django, and explain its mechanics and how it was put together.
In today&#8217;s example, the goal was pretty straightforward. We have a model class, Topic, that has a one-to-many relationship to a ThreadedComment model class. Each ThreadedComment [...]]]></description>
			<content:encoded><![CDATA[<p>So the purpose of this post is just to look at a neat way of solving a problem in Django, and explain its mechanics and how it was put together.</p>
<p>In today&#8217;s example, the goal was pretty straightforward. We have a model class, <code>Topic</code>, that has a one-to-many relationship to a <code>ThreadedComment</code> model class. Each <code>ThreadedComment</code> for each <code>Topic</code>, has a <code>User</code> associated with it; furthermore the <code>Topic</code> itself as a <code>User</code> associated with it (the creator of the topic).</p>
<p><span id="more-85"></span></p>
<p>The issue here is that it&#8217;s not actually a straightforward relationship between <code>Topic</code> and <code>ThreadedComment</code>, due to some complicating factors beyond the scope of this discussion. Suffice it to say what we&#8217;re looking for is a list of users who are participants in the discussion, inclusive of the topic creator. But we&#8217;re not looking for just any old list &#8212; what we need is a QuerySet, for the reason that we are making use of some specialized tags in our templates that require data to be in a QuerySet.</p>
<p>Here&#8217;s a quick example of what we want the interface to look like in the template:</p>
<pre class="brush: xml;">
	&lt;ul&gt;
	{% for participant in topic.participants %}
		&lt;li&gt;{{ participant.name }}&lt;/li&gt;
	{% endfor %}
	&lt;/ul&gt;
</pre>
<p>So let&#8217;s do this step by step.</p>
<p>First, let&#8217;s get a list of the <code>ThreadedComment</code> objects we need:</p>
<pre class="brush: python;">
ThreadedComment.public.all_for_object(topic))
</pre>
<p>The <code>all_for_object()</code> method is one of the &#8220;complications&#8221; we were referring to above. All we care about is that it returns a set of <code>ThreadedComment</code> objects for a given topic.</p>
<p>Okay, but now that we have this set of objects, how are we going to return a QuerySet that yields us User objects?</p>
<p>My co-worker actually showed this to me, so I&#8217;ll share it here. We&#8217;ll use <code>in</code> keyword argument in <code>filter()</code>, which maps to the SQL <code>IN</code> clause. The Django documentation has a simple example:</p>
<pre class="brush: python;">
Entry.objects.filter(id__in=[1, 3, 4])
</pre>
<p>is equivalent to:</p>
<pre class="brush: sql;">
SELECT ... WHERE id IN (1, 3, 4)
</pre>
<p>So that&#8217;s just what we&#8217;re going to do: pass a list of user ids as an <code>in</code> keyword argument to identify the users we want.</p>
<p>First, let&#8217;s extend our original QuerySet to get the values we need as a list:</p>
<pre class="brush: python;">
ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)
</pre>
<p>One thing is missing &mdash; we need to include the user id of the topic creator, as I mentioned above. We&#8217;ll just evaluate the QuerySet to a list and then add the topic creator to it:</p>
<pre class="brush: python;">
list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
</pre>
<p>Now let&#8217;s take the list of ids and pass it to a QuerySet that we&#8217;ll return <code>User</code> objects. Our list goes in the <code>pk__in</code> keyword argument:</p>
<pre class="brush: python;">
User.objects.filter(
    pk__in=list(
        list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
    )
)
</pre>
<p>Now let&#8217;s add this as a method <code>participants()</code> to the <code>Topic</code> model and throw a <code>@property</code> decorator on it so we can call it as an attribute:</p>
<pre class="brush: python;">
@property
def participants(self):
    return User.objects.filter(
        pk__in=list(
            list(ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)) + [self.creator.id]
        )
    )
</pre>
<p>And that&#8217;s all there is to it.</p>
<p>What I love about this approach is that it&#8217;s a pattern that fits in to so many places (so many that I almost feel like it deserves a higher level abstraction within the QuerySet API). There are variations that make it slightly more efficient as well; for example, if I didn&#8217;t need to append the topic creator id in my example, then I could have passed the list of ids as a query as opposed to evaluating it:</p>
<pre class="brush: python;">
User.objects.filter(
    pk__in=ThreadedComment.public.all_for_object(self).values_list('user_id', flat=True)).query
)
</pre>
<p>The advantage here is that this is evaluated as a subselect statement, so it only requires a single database call.</p>
<p>Anyhow, this technique is really fantastic when you have a set of related objects that for whatever reason you aren&#8217;t able to easily obtain as a QuerySet. Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://furrybrains.com/2008/10/23/using-in-in-querysets-in-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
