<?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>iamtgc &#187; Django</title>
	<atom:link href="http://iamtgc.com/category/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://iamtgc.com</link>
	<description></description>
	<lastBuildDate>Thu, 02 Feb 2012 00:15:10 +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>httpBL Middleware for Django</title>
		<link>http://iamtgc.com/2008/02/11/httpbl-middleware-for-django/</link>
		<comments>http://iamtgc.com/2008/02/11/httpbl-middleware-for-django/#comments</comments>
		<pubDate>Mon, 11 Feb 2008 17:36:54 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://iamtgc.com/2008/02/11/httpbl-middleware-for-django/</guid>
		<description><![CDATA[Inspired by Project Honeypot and the http:BL WordPress Plugin, I decided to write a similar plugin for Django. The Http:BL API is well documented here and there are implementations for Joomla, Drupal and numerous others. As my framework of choice &#8230; <a href="http://iamtgc.com/2008/02/11/httpbl-middleware-for-django/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Inspired by <a href="http://www.projecthoneypot.org/">Project Honeypot</a> and the <a href="http://wordpress.org/extend/plugins/httpbl/">http:BL WordPress Plugin</a>, I decided to write a similar plugin for Django.  The Http:BL API is well documented <a href="http://www.projecthoneypot.org/httpbl_api">here</a> and there are implementations for <a href="http://code.google.com/p/joomla-httpbl/">Joomla</a>, <a href="http://drupal.org/project/httpbl">Drupal</a> and <a href="http://www.projecthoneypot.org/httpbl_implementations.php">numerous others.</a></p>
<p>As my framework of choice is Django, we&#8217;ll focus on that.<br />
<span id="more-11"></span><br />
To beign, you&#8217;ll need to request your http:BL API Access Key <a href="http://www.projecthoneypot.org/httpbl_configure.php">here</a>.  It is also suggested, but not required, that you <a href="http://www.projecthoneypot.org/manage_quicklink.php">configure your QuickLink</a> (more on this below).</p>
<p>Now, in your <strong>settings.py</strong> you&#8217;ll want to add your http:BL API Key &#8216;HTTPBLKEY&#8217;.</p>
<pre class="brush:plain;">
HTTPBLKEY = 'opqrstuvwxyz'
</pre>
<p>Next you&#8217;ll need to include your httpbl middleware in <strong>MIDDLEWARE_CLASSES</strong></p>
<pre class="brush:plain;">
MIDDLEWARE_CLASSES = (
    ....
    'projectname.middleware.httpbl.HttpBLMiddleware',
    ....
)
</pre>
<p>You&#8217;ll want to place the middleware file, named <strong>httpbl.py</strong> in your <strong>project/middleware</strong> directory. If this does not exist, you will need to create it and place an empty __init__.py file in it.</p>
<p><strong>project/middleware/httpbl.py</strong><a href="http://django-httpbl-middleware.googlecode.com/files/httpbl.py"><i>(download)</i></a></p>
<pre class="brush:py;">
from django.conf import settings
from django.http import HttpResponseNotFound, HttpResponsePermanentRedirect
import socket

class HttpBLMiddleware(object):
   """
   "HttpBL" Middleware by iamtgc@gmail.com
   """
   def __init__(self, age=None, threat=None, classification=None):
      if age is None:
         self.age = getattr(settings, 'HTTPBLAGE', 14)
      else:
         self.age = age
      if threat is None:
         self.threat = getattr(settings, 'HTTPBLTHREAT', 30)
      else:
         self.threat = threat
      if classification is None:
         self.classification = getattr(settings, 'HTTPBLCLASS', 7)
      else:
         self.classification = classification

   def process_request(self, request):

      if settings.HTTPBLKEY:
         ip = request.META.get('REMOTE_ADDR')
         iplist = ip.split('.')
         iplist.reverse()

         domain = 'dnsbl.httpbl.org'

         query = settings.HTTPBLKEY + "." + ".".join(iplist) + "." + domain

         try:
            result = socket.gethostbyname(query)
         except socket.gaierror:
            return None

         resultlist = result.split('.')

         if (int(resultlist[1]) <= self.age and int(resultlist[2]) >= self.threat and int(resultlist[3]) &#038; self.classification > 0):
            if settings.HTTPBLREDIRECT:
               return HttpResponsePermanentRedirect(settings.HTTPBLREDIRECT)
            else:
               return HttpResponseNotFound('
<h1>Not Found</h1>

')

      return None
</pre>
<p>This should be all you need to be on your way and protecting your Django site from suspicious hosts, email harvesters, and comment spammers.  But who am I to tell you what your settings should be?  Here are the additional settings you can define in <strong>settings.py</strong>.  The octets that these variables correspond with are fully documented in <a href="http://www.projecthoneypot.org/httpbl_api.php">Http:BL API Specification &#8211; Query Responses</a>.</p>
<pre class="brush:shell;">
# HTTBLAGE - represents the number of days since activity was seen on the Honey Pot network.  Defaults to 14
HTTPBLAGE = 14
# HTTPBLTHREAT = threat score assigned by Project Honey Pot, higher number is more of a threat.  Defaults to 30
HTTPBLTHREAT = 30
# HTTPBLCLASS = bitset category, see API doc for more details.  Defaults to 7 = Suspicious &#038; Harvester &#038; Comment Spammer
HTTPBLCLASS = 7
</pre>
<p>As mentioned above, it is suggested that you configure a QuickLink. If configured, you should set HTTPBLREDIRECT to your QuickLink URL to redirect any &#8220;bad&#8221; traffic away from your site and into a honeypot.  Again, this would be defined in <strong>settings.py</strong>.</p>
<pre class="brush:shell;">
# HTTPBLREDIRECT = QuickLink Honey Pot URL that we direct the bad traffic to.  Default = "Not Found" response, no redirection.
HTTPBLREDIRECT = 'http://some.honeypot.url/goes/here'
</pre>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2008/02/11/httpbl-middleware-for-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>reCAPTCHA Mailhide template filter for Django</title>
		<link>http://iamtgc.com/2007/09/06/recaptcha-mailhide-template-filter-for-django/</link>
		<comments>http://iamtgc.com/2007/09/06/recaptcha-mailhide-template-filter-for-django/#comments</comments>
		<pubDate>Fri, 07 Sep 2007 02:11:36 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://iamtgc.com/2007/09/06/recaptcha-mailhide-template-filter-for-django/</guid>
		<description><![CDATA[reCAPTCHA&#8217;s Mailhide is a captcha that &#8220;helps you protect your inbox by asking people to solve a reCAPTCHA before they can view your email address.&#8221; The Mailhide API is well documented, information on it&#8217;s inner workings can be found here. &#8230; <a href="http://iamtgc.com/2007/09/06/recaptcha-mailhide-template-filter-for-django/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://mailhide.recaptcha.net/">reCAPTCHA&#8217;s Mailhide</a> is a captcha that &#8220;helps you protect your inbox by asking people to solve a reCAPTCHA before they can view your email address.&#8221;</p>
<p>The Mailhide API is well documented, information on it&#8217;s inner workings can be found <a href="http://recaptcha.net/apidocs/mailhide/">here</a>.</p>
<p>In order to leverage Mailhide, you will need to <a href="http://mailhide.recaptcha.net/apikey">request your API Key</a>.</p>
<p>Additionally, you&#8217;ll also need amk&#8217;s <a href="http://www.amk.ca/python/code/crypto">Python Cryptography Toolkit</a>.  The version of the Python Cryptography Toolkit tested is 2.0.1, but any version that supports AES should work.</p>
<p>Now, once you have installed the necessary packages and requested your API Key, it&#8217;s time to put them to use.<br />
<span id="more-12"></span><br />
In your <b>settings.py</b> you&#8217;ll want to add your API Keys in their respective variables, MAILHIDE_PUB_KEY is your Public Key, and MAILHIDE_PRIV_KEY is your Private Key.</p>
<pre class="brush:plain;">
MAILHIDE_PUB_KEY = '01QvLWux5x-zHdXXYv-VumOg=='
MAILHIDE_PRIV_KEY = '41F69FFAF768AE6ED69A96C15A13252A'
</pre>
<p>Next, you&#8217;ll want to add the filter, I&#8217;ve named this <b>mailhide.py</b> and it should reside in your <b>app/templatetags/</b> directory.  If this does not exist, you will need to create it and place an empty <b>__init__.py</b> file in it.  Additional information on <i>Extending the template system</i> can be found <a href="http://www.djangoproject.com/documentation/templates_python/">here</a>. </p>
<p><b>app/templatetags/mailhide.py</b> <a href="http://django-mailhide-filter.googlecode.com/files/mailhide.py"><i>(download)</i></a></p>
<pre class="brush:py;">
import base64
import binascii

from Crypto.Cipher import AES
from django.conf import settings
from django import template

register = template.Library()

def pad_string (str, block_size):
    numpad = block_size - (len (str) % block_size)
    return str + numpad * chr (numpad)

def enc_string(str):
    key = binascii.unhexlify(settings.MAILHIDE_PRIV_KEY)
    mode = AES.MODE_CBC
    iv = '\000' * 16
    obj = AES.new(key, mode, iv)
    return obj.encrypt(str)

@register.filter()
def mailhide(value):
    args = {}
    padded_value = pad_string(value, 16)
    encrypted_value = enc_string(padded_value)

    args['public_key'] = settings.MAILHIDE_PUB_KEY
    args['encrypted_email'] = base64.urlsafe_b64encode(encrypted_value)
    args['domain'] = value[value.index('@')+1:]

    return '''<a href="http://mailhide.recaptcha.net/d?k=%(public_key)s&#038;c=%(encrypted_email)s"
                onclick="window.open('http://mailhide.recaptcha.net/d?k=%(public_key)s&#038;c=%(encrypted_email)s', '',
                'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300');
                return false;" title="Reveal this e-mail address">...@%(domain)s</a>''' % args
</pre>
<p>This filter expects an email address, <b>fred.flinstone@domain.tld</b>, for example, and will return a link to the captcha titled <b>&#8230;@domain.tld</b>.</p>
<p>Here is an example of how you would use this in your template.<br />
<b>templates/app/index.html</b></p>
<pre class="brush:py;">
{% load mailhide %}

{{ user_obj.email|mailhide }}
</pre>
<p>Enjoy!</p>
<p>Please leave any feedback in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2007/09/06/recaptcha-mailhide-template-filter-for-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Stored Procedures and Django</title>
		<link>http://iamtgc.com/2007/07/25/stored-procedures-and-django/</link>
		<comments>http://iamtgc.com/2007/07/25/stored-procedures-and-django/#comments</comments>
		<pubDate>Thu, 26 Jul 2007 01:44:57 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Postgres]]></category>

		<guid isPermaLink="false">http://iamtgc.com/2007/07/25/stored-procedures-and-django/</guid>
		<description><![CDATA[Since it is not always possible, or efficient, to accomplish the database queries you would like using the Django Database API, many developers will find themselves needing to escape the constraints of the API and leverage stored procedures. For scenarios &#8230; <a href="http://iamtgc.com/2007/07/25/stored-procedures-and-django/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Since it is not always possible, or efficient, to accomplish the database queries you would like using the Django Database API, many developers will find themselves needing to escape the constraints of the API and leverage stored procedures. </p>
<p>For scenarios when you would like to execute stored procedures, or any other custom SQL, you can use the Python DB API as suggested <a href="http://www.djangoproject.com/documentation/model-api/#executing-custom-sql">here</a> in the Django documentation.</p>
<p>So, to begin, let&#8217;s examine the following stored procedure.  This example was taken from the <a href="http://www.postgresql.org/docs/8.2/static/plpgsql-cursors.html">Postgres documentation on Cursors.</a><br />
<span id="more-8"></span></p>
<pre class="brush:sql;">
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '
BEGIN
    OPEN $1 FOR SELECT col FROM test;
    RETURN $1;
END;
' LANGUAGE plpgsql;
</pre>
<p>This stored procedure takes the name of a <i>refcursor</i> as an argument, executes a SELECT, and returns a <i>refcursor</i> containing the results of the SELECT.  Using the tool psql the stored procedure can be executed in the following way.</p>
<pre class="brush:sql;">
BEGIN;
SELECT reffunc('funccursor');
FETCH ALL IN funccursor;
COMMIT;
</pre>
<p>It is important that this stored procedure is wrapped in a transaction to be able to FETCH the contents of the returned <i>refcursor</i>.</p>
<p>Now, let&#8217;s examine how you&#8217;d accomplish this in Django</p>
<pre class="brush:py;">
from django.db import connection
cursor = connection.cursor()
cursor.execute("BEGIN")
cursor.execute("SELECT reffunc('funccursor')")
cursor.execute("FETCH ALL IN funccursor")
results = cursor.fetchall()
cursor.execute("COMMIT")
</pre>
<p>Simple!  Now, the contents of the <i>refcursor</i>, in this case <b>funccursor</b> are in <b>results</b>.</p>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2007/07/25/stored-procedures-and-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django on Lighttpd with FastCGI</title>
		<link>http://iamtgc.com/2007/07/04/django-on-lighttpd-with-fastcgi/</link>
		<comments>http://iamtgc.com/2007/07/04/django-on-lighttpd-with-fastcgi/#comments</comments>
		<pubDate>Thu, 05 Jul 2007 01:53:51 +0000</pubDate>
		<dc:creator>tgc</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Lighttpd]]></category>

		<guid isPermaLink="false">http://iamtgc.com/2007/07/04/django-on-lighttpd-with-fastcgi/</guid>
		<description><![CDATA[After having followed the Django documentation on how to use Django with lighttpd and fastcgi numerous times, I had very little success. Being new to Django and very anxious to dive in head first, this was a very frustrating hurdle &#8230; <a href="http://iamtgc.com/2007/07/04/django-on-lighttpd-with-fastcgi/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After having followed the Django documentation on how to use Django with lighttpd and fastcgi numerous times, I had very little success.  Being new to Django and very anxious to dive in head first, this was a very frustrating hurdle to encounter.</p>
<p>In this article I outline the steps which I took that lead to a successful configuration.  This article is not explanation on how to install Django, lighttpd or any of the associated components.  It is, however, my hope that this article will help you get Django running with lighttpd and fastcgi without the frustration.<br /> <br />
<span id="more-7"></span><br />
This example assumes you, jdoe, will set up a django-projects directory to contain multiple django projects, and your first project is a blog. </p>
<pre class="brush:shell;">
$ mkdir /home/jdoe/django-projects

$ cd /home/jdoe/django-projects

$ django-admin.py startproject blog
</pre>
<p>Now we need to setup your fastcgi file, we&#8217;ll place this in <b>/home/jdoe/www/blog/mysite.fcgi</b>, this is assuming your document-root is <b>/home/jdoe/www/blog</b>.</p>
<pre class="brush:py;">
#!/usr/pkg/bin/python2.4
import sys, os

# Add a custom Python path.
sys.path.insert(0, "/home/jdoe/django-projects")

# Switch to the directory of your project. (Optional.)
# os.chdir("/home/jdoe/django-projects/blog")

# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "blog.settings"

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
</pre>
<p>Okay, now that you&#8217;ve set up your fcgi file, let&#8217;s test it out</p>
<pre class="brush:shell;">
$ python2.4 ./mysite.fcgi
WSGIServer: missing FastCGI param REQUEST_METHOD required by WSGI!
WSGIServer: missing FastCGI param SERVER_NAME required by WSGI!
WSGIServer: missing FastCGI param SERVER_PORT required by WSGI!
WSGIServer: missing FastCGI param SERVER_PROTOCOL required by WSGI!
Traceback (most recent call last):
  File "/usr/pkg/lib/python2.4/site-packages/flup-0.5-py2.4.egg/flup/server/fcgi_base.py", line 558, in run
    protocolStatus, appStatus = self.server.handler(self)
  File "/usr/pkg/lib/python2.4/site-packages/flup-0.5-py2.4.egg/flup/server/fcgi_base.py", line 1112, in handler
    result = self.application(environ, start_response)
  File "/usr/pkg/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django/core/handlers/wsgi.py", line 148, in __call__
    response = self.get_response(request.path, request)
  File "/usr/pkg/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django/core/handlers/base.py", line 59, in get_response
    response = middleware_method(request)
  File "/usr/pkg/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django/middleware/common.py", line 40, in process_request
    if settings.APPEND_SLASH and (old_url[1][-1] != '/') and ('.' not in old_url[1].split('/')[-1]):
IndexError: string index out of range
Content-Type: text/html

&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"&gt;
&lt;html&gt;&lt;head&gt;
&lt;title&gt;Unhandled Exception&lt;/title&gt;
&lt;/head&gt;&lt;body&gt;
&lt;h1&gt;Unhandled Exception&lt;/h1&gt;
&lt;p&gt;An unhandled exception was thrown by the application.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</pre>
<p>This is the output you can expect to see, if you happen to get the following output instead</p>
<pre class="brush:shell;">
$ python2.4 ./mysite.fcgi
Traceback (most recent call last):
  File "./mysite.fcgi", line 15, in ?
    runfastcgi(method="threaded", daemonize="false")
TypeError: runfastcgi() got an unexpected keyword argument 'method'
</pre>
<p>You should replace </p>
<pre class="brush:py;">
runfastcgi(method="threaded", daemonize="false")
</pre>
<p>in mysite.fcgi with</p>
<pre class="brush:py;">
runfastcgi(["method=threaded", "daemonize=false"])
</pre>
<p>Now the last step is setting up lighttpd, the following sets up django in your domain <b>blog.domain.tld</b>, but the important part is the fastcgi.server block.  The primary change that I had to make from the Django documentation is the addition of the bin-path variable.</p>
<pre class="brush:plain;">
$HTTP["host"] =~ "(^|\.)blog\.domain\.tld$" {
        server.document-root = "/home/jdoe/www/blog"
        accesslog.filename = "/var/log/lighttpd/blog.domain.tld-access.log"

        fastcgi.server = (
                ".fcgi" => (
                        "localhost" => (
                                "bin-path" => "/home/jdoe/www/blog/mysite.fcgi",
                                "socket" => "/home/jdoe/tmp/mysite.sock",
                                "check-local" => "disable",
                                "min-procs" => 2,
                                "max-procs" => 4,
                        )
                ),
        )

        alias.url = (
                "/media/" => "/home/jdoe/www/blog/media/",
        )
        url.rewrite-once = (
                "^(/media.*)$" => "$1",
                "^/favicon\.ico$" => "/media/favicon.ico",
                "^(/.*)$" => "/mysite.fcgi$1",
        )
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://iamtgc.com/2007/07/04/django-on-lighttpd-with-fastcgi/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

