<?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>Nadav Samet&#039;s Blog &#187; Filters</title>
	<atom:link href="http://www.thesamet.com/blog/tags/filters/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thesamet.com</link>
	<description>Because everyone needs a blog</description>
	<lastBuildDate>Sat, 07 Aug 2010 21:58:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Filters 0.1 Released</title>
		<link>http://www.thesamet.com/blog/2006/12/07/filters-01-released/</link>
		<comments>http://www.thesamet.com/blog/2006/12/07/filters-01-released/#comments</comments>
		<pubDate>Thu, 07 Dec 2006 09:18:51 +0000</pubDate>
		<dc:creator>thesamet</dc:creator>
				<category><![CDATA[Filters]]></category>
		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://www.thesamet.com/blog/2006/12/07/filters-01-released/</guid>
		<description><![CDATA[Filters is a Python package that provides shell-like data processing operators for generation of web content. Filters is designed to work together with a template-engine like Kid and Genshi. What is a filter? We&#8217;ll start with an example. ${ identity.is_anonymous() &#8230; <a href="http://www.thesamet.com/blog/2006/12/07/filters-01-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><i><b>Filters</b> is a Python package that provides shell-like data processing operators for generation of web content. <b>Filters</b> is designed to work together with a template-engine like Kid and Genshi.</i></p>
<h2>What is a filter?</h2>
<p>We&#8217;ll start with an example.</p>
<p><code>
<pre>${ identity.is_anonymous() | tg.yesno() }</pre>
<p></code><br />
The output of this will be the value returned by <code>is_anonymous()</code> after being processed by the <code>yesno</code> filter, which translates a boolean to either &#8220;yes&#8221; or &#8220;no&#8221;.</p>
<p>Some filters can do really cool stuff. For instance, consider this:</p>
<ul>
<li><code>{{ file_size | tg.filesizeformat() }}</code>: this would print the size in a human-readable format (i.e. 17 KB, 102.4MB and so on). </li>
<li><code>{{ story.text | tg.escape() | tg.linebreaks() }}</code>: this will escape all ampersands from the text and then convert all newlines to &lt;p&gt; and &lt;br/&gt;. This also demonstrates that filters can be chained.</li>
<li><code>You have {{egg_count}} egg{{egg_count | tg.pluralize()}} left</code>: will pluralize the egg noun with the suffix &#8217;s&#8217; if <code>egg_count</code> is not one.
</ul>
<p>The main goal of <i>Filters</i> is to provide a rich set of easy-to-use operations that are commonly needed in real-world applications. </p>
<p>After implementing this <a href="http://www.thesamet.com/blog/2006/12/04/django-like-filters-for-kid/">in a form of patches for Kid and Genshi</a>, Christopher Lenz from Genshi suggested a way to implement this externally to the parsers. The idea is based on <a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/276960">this recipe</a> from the Python Cookbook. This solution enjoys the benefits of using pure Python syntax. This means that we are now using single bar (|) again.</p>
<p>Here&#8217;s how to use it.</p>
<h2>Download and install</h2>
<p>Get this: <a href="http://www.thesamet.com/blog/wp-content/uploads/2006/12/Filters-0.1.tar.gz">Filters-0.1.tar.gz</a>. Extract the archive and run <code>python setup.py install</code>.</p>
<h2>Hook into TurboGears</h2>
<p>Go to controllers.py, add add the following lines:<br />
<code>
<pre>
from filters.core import tg_add_variables
tg_add_variables()
</pre>
<p></code></p>
<p>If you&#8217;d like to have the filters under their own namespace, replace the last line by:<br />
<code>
<pre>
tg_add_variables(pollute=False)
</pre>
<p></code><br />
And the filters will be available under tg.filters instead of under tg.</p>
<h2>Using filters</h2>
<p>Here are some examples demonstrating how to use filters:</p>
<p><code>
<pre>
${ identity.is_anonymous() | tg.yesno() }
</pre>
<p></code></p>
<p><code>
<pre>
You have ${count} cherr${count | tg.pluralize('y,ies') }.
</pre>
<p></code></p>
<p>Note that filters accept their argument in parenthesis. The paranthesis are required even if there are no arguments.</p>
<h2>Writing your own filters</h2>
<p>Basically, a filter is just a function that takes input and possibly some arguments, and returns an output, that will<br />
be passed to the next filter, or to the output. The Filters package provide two decorators to help you with filters. The first is <code>make_filter</code> that transforms your function to a filter class, and the second is <code>register_filter</code> which registers your filter and makes it available inside templates. Here&#8217;s how to use it:</p>
<p><code>
<pre>
from filters.core import register_filter, make_filter

@register_filter()
@make_filter()
def shorturl(input, max_length=50):
    return input.split('?')[0][:max_length]
</pre>
<p></code></p>
<p>Then, inside your template:<br />
<code>
<pre>
${ my_url | tg.shorturl() }
</pre>
<p></code> or <code>
<pre>
${ my_url | tg.shorturl(25) }
</pre>
<p></code></p>
<p>Good luck, and feel free to leave here questions or comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thesamet.com/blog/2006/12/07/filters-01-released/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

