<?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>zoia.org &#187; Django</title>
	<atom:link href="http://www.zoia.org/blog/category/programming/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zoia.org/blog</link>
	<description>Por Roberto Zoia</description>
	<lastBuildDate>Thu, 22 Dec 2011 22:07:39 +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>Google App Engine</title>
		<link>http://www.zoia.org/blog/2008/04/10/google-app-engine/</link>
		<comments>http://www.zoia.org/blog/2008/04/10/google-app-engine/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 17:26:06 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[app_engine]]></category>
		<category><![CDATA[web_framework]]></category>
		<category><![CDATA[web_programming]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/?p=195</guid>
		<description><![CDATA[Hace unos días Google lanzó Google App Engine. Me ahorro detalles que ya se han comentado en otros sitios. Por ahora estoy &#8220;en cola&#8221; esperando una cuenta de prueba. Algunos detalles: el lenguaje de programación es Python 2.5, permite trabajar con la mayoría de Python web frameworks y para comodidad del desarrollador incluye Django 0.96.1. [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Hace unos días Google lanzó <a href="http://code.google.com/appengine">Google App Engine</a>.  Me ahorro detalles que ya se han <a href="http://eric.themoritzfamily.com/2008/04/08/google-apps-engine-without-django-colored-glasses/">comentado</a> <a href="http://hackermojo.com/mt-static/archives/2008/04/google-and-django-for-newspapers.html">en</a> <a href="http://lazutkin.com/blog/2008/apr/8/google-app-engine-first-look/">otros</a> <a href="http://simonwillison.net/2008/Apr/8/running/">sitios</a>.</p>

<p>Por ahora estoy &#8220;en cola&#8221; esperando una cuenta de prueba. Algunos detalles: el lenguaje de programación es Python 2.5, permite trabajar con la mayoría de Python <em>web frameworks</em> y para comodidad del desarrollador incluye <a href="http://djangoproject.com">Django</a> 0.96.1.</p>

<p>El video de abajo muestra una aplicación sencilla. (No es ninguna novedad, lo saqué de la página de Google App Engine.)  El framework, en este caso, no es Django (sí usa los templates de Django), pero a los que hayan programado con Django el código les resultará algo familiar.</p>

<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/bfgO-LXGpTM&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/bfgO-LXGpTM&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2008/04/10/google-app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free the Dragon!</title>
		<link>http://www.zoia.org/blog/2008/03/09/free-the-dragon/</link>
		<comments>http://www.zoia.org/blog/2008/03/09/free-the-dragon/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 03:17:56 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[activestate]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[Komodo]]></category>
		<category><![CDATA[mozilla code base]]></category>
		<category><![CDATA[python cookbook]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2008/03/09/free-the-dragon/</guid>
		<description><![CDATA[Hace unos días ActiveState ha sacado una versión open source de Komodo Edit, bajo los mismos términos que la licencia de Firefox. Esta decisión tiene sentido, pues Komodo Edit comparte parte del código fuente base de Mozilla. Desde hace años, ActiveState desarrolla herramientas para programar en Perl, Python, PHP, Ruby y otros. También aloja varios [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Hace unos días ActiveState ha sacado una versión open source de Komodo Edit, bajo los mismos términos que la licencia de Firefox.  Esta decisión tiene sentido, pues Komodo Edit comparte parte del código fuente base de Mozilla.</p>

<div style="float: left; padding: 5px 10px 5px 0px;"><a href='http://www.zoia.org/blog/wp-content/uploads/2008/03/komodoedit.jpg' rel='lightbox' title='Komodo Edit editando un archivo de Python'><img src='http://www.zoia.org/blog/wp-content/uploads/2008/03/komodoedit_thumb.jpg' alt='Komodo Edit editando un archivo de Python' /></a></div>

<p>Desde hace años, ActiveState  desarrolla herramientas para programar en Perl, Python, PHP, Ruby y otros.  También aloja varios &#8220;Cookbooks&#8221; (recetarios) en su website, por ejemplo, el imprescindible <a href="http://aspn.activestate.com/ASPN/Cookbook/Python/">Python Cookbook</a>.</p>

<div style="clear: both"> </div>

<div style="float: right; padding: 5px 10px 5px 0px;"><a href='http://www.zoia.org/blog/wp-content/uploads/2008/03/komodoeditextensions.jpg' rel='lightbox' title='Komodo Edit extensions'><img src='http://www.zoia.org/blog/wp-content/uploads/2008/03/komodoeditextensions_thumb.jpg' alt='Komodo Edit extensions' /></a></div>

<p>Un detalle interesante, relacionado precisamente con Mozilla, son las extensiones que usa Komodo Edit.  Basta ver el segundo screenshot para entender a qué me refiero:  son extensiones escritas en XUL, el mismo sistema que usan Firefox y Thunderbird.  Y, otra cosa que se puede ver en el screenshot, Komodo viene con una extensión para desarrollar con <a href="http://www.djangoproject.com">Django</a>.</p>

<p>Hay versiones para Linux, MacOs y Windows, y se puede <a href="http://www.activestate.com/Products/komodo_ide/komodo_edit.mhtml">descargar del website de ActiveState</a>.</p>

<div style="clear: both"> </div>
]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2008/03/09/free-the-dragon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django file upload</title>
		<link>http://www.zoia.org/blog/2007/07/29/django-file-upload/</link>
		<comments>http://www.zoia.org/blog/2007/07/29/django-file-upload/#comments</comments>
		<pubDate>Sun, 29 Jul 2007 22:26:14 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2007/07/29/django-file-upload/</guid>
		<description><![CDATA[Some interesting examples on how to handle file uploads using Django: Code snippet posted on Djangosnippets. The file is saved by declaring a save() method in the form class. This method is invoked when calling form.save(), which is standard Django newforms practice. (Note that this snipped uses clean_data. As of Django version 0.96, clean_data has [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Some interesting examples on how to handle file uploads using <a href="http://www.djangoproject.com">Django</a>:</p>

<ul>
<li>Code snippet posted on <a href="http://www.djangosnippets.org/snippets/95/">Djangosnippets</a>. The file is saved by declaring a <code>save()</code> method in the form class.  This method is invoked when calling <code>form.save()</code>, which is standard Django newforms practice. (Note that this snipped uses <code>clean_data</code>.  As of Django version 0.96, <code>clean_data</code> <a href="http://code.djangoproject.com/changeset/5237">has been renamed</a> to <code>cleaned_data</code>, so you will have to change the code or it won&#8217;t work)</li>
<li><a href="http://www.oluyede.org/blog/2007/03/18/django-image-uploading-validation-and-newforms/">Django image upload and validation</a>. The author uses a model for the file and its related data.  The uploaded file is saved by calling the <code>save_FOO_file</code> method. (This method is automatically provided by Django for fields declared as <code>models.ImageField</code> or <code>models.FileField</code> in the model. See the <a href="http://www.djangoproject.com/documentation/db-api/#save-foo-file">db-api documentation</a>.)</li>
<li><a href="http://batiste.dosimple.ch/blog/2007-05-13-1/">Django image upload, form_for_instance and monkey-patching</a>.  The example code creates a form class from <code>request.user</code> by calling <code>form_for_instance</code>.  The resulting class in then monkey-patched to insert the avatar image validation code.  (Although the code is interesting the monkey patch seems unnecessary.  I wouldn&#8217;t mind inserting the avatar validation method in a <code>UserProfileForm</code> class derived from <code>form.Forms</code>.  The code would be certainly clearer:  I think KISS takes precedence over DRY in this case.)</li>
</ul>

<p>Interesting, there seems to be no easy way of limiting the uploaded file size.  The file can be rejected at validation time, but the data would have already been transfered.</p>

<h2>A file upload recipe</h2>

<p>After reading those posts, I think that a good recipe for handling file uploads in Django would be:</p>

<ul>
<li>Write a django model for the uploaded file and its related data. Using a Django model makes sense, because it is usually necessary for the application to keep track of the uploaded files.</li>
<li>Write a subclass of <code>form.Forms</code> and declare a <code>clean_FOO</code> method for each <code>models.FileInput</code> or <code>models.ImageInput</code> fields declared in the model class.  These clean_FOO methods are used to validate the uploaded files.</li>
<li>use a django view to receive the POST data, or display the form if no data is posted or errors are found.</li>
<li>validate the uploaded file or files by triggering the standard django newforms validation mechanism:  <code>is_valid()</code>.</li>
<li>save the file or files getting the data directly from the <code>request.FILES</code> object, by writing a <code>save()</code> method for the subclassed form or by calling <code>save_FOO_file</code> for the model instance.</li>
</ul>

<h2>A simpler way to upload a file</h2>

<p>The following short <a href="http://www.djangoproject.com">Django</a> example uses no data models, does no data validation, and saves the file directly to disk using python standard file functions.  It is just a simple test I wrote to get familiar with the <code>request.FILES</code> object. This is not production code:  it could be used to execute an arbitrary script on the server.
The directory where the file is to be saved must be writable by the user that is running the Django server script. (The example uses MEDIA_ROOT as defined in <code>settings.py</code>.)</p>

<h3>file: views.py</h3>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
from django import http
from django import newforms as forms
from django.shortcuts import render_to_response
from djangotest.settings import MEDIA_ROOT



class SimpleFileForm(forms.Form):
    file = forms.Field(widget=forms.FileInput, required=False)


def directupload(request):
    &quot;&quot;&quot;
    Saves the file directly from the request object. 
    Disclaimer:  This is code is just an example, and should
    not be used on a real website.  It does not validate
    file uploaded:  it could be used to execute an 
    arbitrary script on the server. 
    &quot;&quot;&quot;

    template = 'fileupload.html'

    if request['method'] == 'POST':
        if 'file' in request.FILES:
            file = request.FILES['file']

            # Other data on the request.FILES dictionary:
            #   filesize = len(file['content'])   
            #   filetype = file['content-type'] 

            filename = file['filename']

            fd = open('%s/%s' % (MEDIA_ROOT, filename), 'wb')
            fd.write(file['content'])
            fd.close()

            return http.HttpResponseRedirect(' upload_success.html')
    else:
        # display the form
        form = SimpleFileForm()
        return render_to_response(template, { 'form': form })

</pre>


<h3>file:  fileupload.html</h3>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
{% extends &quot;base.html&quot; %}

{% block body  %}
     &lt;h1&gt;Upload a file&lt;/h1&gt;
     &lt;form action=&quot;.&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
             {{ form }}
             &lt;input type=&quot;submit&quot; value=&quot;Upload&quot; /&gt;
     &lt;/form&gt;
{% endblock %}
</pre>

]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2007/07/29/django-file-upload/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Django newforms documentation updated</title>
		<link>http://www.zoia.org/blog/2007/07/12/django-newforms-documentation-updated/</link>
		<comments>http://www.zoia.org/blog/2007/07/12/django-newforms-documentation-updated/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 01:39:19 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2007/07/12/django-newforms-documentation-updated/</guid>
		<description><![CDATA[The Django newforms documentation has been updated some days ago. It includes an explanation on how to use form_for_models and form_for_instance and provides some examples. More interesting, however, is when not to use them: &#8220;If you want to create a form whose fields map to more than one model, or a form that contains fields [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>The <a href="http://www.djangoproject.com/documentation/newforms">Django newforms documentation</a> has been updated some days ago. It includes <a href="http://www.djangoproject.com/documentation/newforms/#generating-forms-for-models">an explanation</a> on how to use <code>form_for_models</code> and <code>form_for_instance</code> and provides some examples.</p>

<p>More interesting, however, is when <em>not</em> to use them:  <i>&#8220;If you want to create a form whose fields map to more than one model, or a form that contains fields that aren’t on a model, you shouldn’t use these shortcuts.&#8221;</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2007/07/12/django-newforms-documentation-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using dynamic choices with Django newforms and custom widgets</title>
		<link>http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/</link>
		<comments>http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/#comments</comments>
		<pubDate>Mon, 23 Apr 2007 23:28:30 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/</guid>
		<description><![CDATA[Most of the examples I have found on the web about replacing the default Django newforms widgets use hard coded values for the list of choices the widget displays. But those hard coded examples fall short when the widgets are bounded to many-to-many fields or to foreign keys in the model class. That is, when [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Most of the examples I have found on the web about replacing the default <a href="http://www.djangoproject.com" target="_blank">Django</a> <code>newforms</code> widgets use hard coded values for the list of choices the widget displays.  But those hard coded examples fall short when the widgets are bounded to many-to-many fields or to foreign keys in the model class.   That is, when the list of choices is generated dynamically at run time, read from a database table.</p>

<p>The solution is obvious simple:  fetch the dictionary of choices from the original widget, and use it as a parameter for your new custom widget.</p>

<p>It sounds simple, and it is.  But it took me some time to figure out how to do it.  The Django <code>newforms</code> lilbrary documentation is still work in progress, at least at the time of this writing. I could not found where the original widgets were stored in the Form instance.  Thankfully, Django is an open source project, and Python has an interactive shell mode.  Inspection of the source code and regression tests, and some playing with the Python shell is really an enlightening process.  Anyway, I am posting this on the blog for further reference.  I also include a working example of a sample Django blogging application I wrote for testing:  pretty basic, but it and ilustrates, among other things, the use of custom widgets with dynamic choices.</p>

<p>Maybe the explanaition is &#8220;over-verbose&#8221;&#8230; suggestions accepted.</p>

<h2>Don&#8217;t hit the database twice</h2>

<p>Consider the following model class:</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# models.py Models for django blog application
from django.db import models

class Tag(models.Model):
    tag = models.CharField(maxlength=50)

class Author(models.Model):
    name = models.CharField(maxlength=100)
    email = models.EmailField()

class Article(models.Model):
        (...)
    author = models.ForeignKey(Author)
    tags = models.ManyToManyField(Tag)
</pre>


<p>The standard method for displaying a form for the model class in a webpage is to subclass forms.Form, create an instance of the subclass and return the rendered the template.  Examples of this can be found on the Django website and on the web.</p>

<p>Django <code>newforms</code> provides two methods that simplify the subclassing of <code>forms.Form</code>:  <code>form_for_instance</code> and <code>form_for_model</code>.  Both methods return a new class:  a subclass of Form, more precisely, tuned to your model class or model instance.  If you have a model class or model instance with a many-to-many relationship, and you don&#8217;t mind displaying the relationship as a listbox on the webpage, then these two methods will take care of querying the database, building the list of options and feeding it to SelectField or a SelectMultipleField widget.</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
          #  ArticleForm is a subclass of form.Form
          ArticleForm = forms.models.form_for_model(Article)
</pre>


<p>The next step is to create an instance of <code>ArticleForm</code>, and return the rendered template:</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
        form = ArticleForm()
        return render_to_response('post.html', { 'form': form })
</pre>


<p>I don&#8217;t like lists for multiple option selection, at least not in webpages.  I prefer checkboxes.  It takes some CSS tweaking to render them correctly and evenly spaced on the webpage, but it greatly enhances the user experience.</p>

<p>The class generated by form_for_model (and by form_for_instance) stores the widgets in a variable named <code>base_fields</code> (a dictionary).  This makes it simple to replace any of the default widgets with any other widget, provided it makes sense to do so.  For example, the following code replaces the <code>author</code> and <code>tags</code> widgets with a RadioSelect widget and a CheckboxSelectMultiple widget:</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
        ArticleForm.base_fields['tags'].widget = CheckboxSelectMultiple(choices= ... )
        ArticleForm.base_fields['author'].widget = RadioSelect(choices= ... )
</pre>


<p>The only thing left is to provide the list of choices that both <code>CheckboxSelectMultiple</code> and <code>RadioSelect</code> constructors expect as one of their parameters.  One way to build such lists is to query the database and fetch the entries for the Tag and Author classes. Something like <code>tagChoices = Tag.objects.all()</code> and <code>authorChoices = Author.objects.all()</code>.  Convert the resulting queryset to a dictionary and use it as a parameter to the RadioSelect widget constructor.</p>

<p>But this is querying the database twice and for the same data each time the form is displayed on the webpage:  once for the original SelectMultiple widget, and then again for the custom widget.  And it would be a shame to have your name on such code&#8230;  Obviously, this can be avoided by retrieving the list of choices from the original SelectMultiple widget and using it as the list of choices for our custom widget:</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
        ArticleForm = forms.models.form_for_model(Article)

        ArticleForm.base_fields['tags'].widget = CheckboxSelectMultiple(
                choices=ArticleForm.base_fields['tags'].choices) 

        ArticleForm.base_fields['author'].widget = RadioSelect(
                choices=ArticleForm.base_fields['author'].choices)

        form = ArticleForm()
        return render_to_response('post.html', { 'form': form })
</pre>


<p>That&#8217;s it.  The Author SelectField gets replaced by radio buttons, and the Tag MultipleSelectField by some nice checkboxes.  The database gets hit only once.  Nothing to be ashamed of.</p>

<h2>A complete example</h2>

<p><strong><u>Updated 2007-5-5</u></strong>: added editpost.html, which was not included by mistake.</p>

<p>The following is a test blog application I wrote.  It uses <code>form_for_instance</code> and <code>form_for_model</code> to define the proper subclass of form, then replaces the standard widgets with custom ones.  The widgets load the Author and Tags choices dynamically.  In addition, creation and edition of the blog posts are handled by the same method.  A regular expression in <code>urls.py</code> converts web page names to slugs as registered in the database, so permalinks are effectively implemented.</p>

<p>This blogging app is really basic:  the Django admin interface is needed to add new tags and authors; no authentication; post slugs have to be hand created; no plugins; etc. But deactivate the edit line in <code>urls.py</code>, use css to pump up the desigh,  edit your posts using the admin interface, and you have a Django-powered miniblog you can start customizing.  Maybe pass the <code>form</code> with the article content to another method, before rendering the template, and write some plugins to pre-process the content prior to show it on the webpage.</p>

<h2>Some screenshots of the Django mini-blog</h2>

<p>This is pretty spartan. Throw in some CSS if you like.</p>

<p><a href='http://www.zoia.org/blog/wp-content/uploads/2007/04/blogindex.jpg' title='Django Blog, main page' rel='lightbox'><img src='http://www.zoia.org/blog/wp-content/uploads/2007/04/blogindex_thumb.jpg' alt='Django Blog, main page' /></a></p>

<p><a href='http://www.zoia.org/blog/wp-content/uploads/2007/04/formcondata.jpg' title='Django blog, edit post' rel='lightbox'><img src='http://www.zoia.org/blog/wp-content/uploads/2007/04/formcondata_thumb.jpg' alt='Django blog, edit post' /></a></p>

<p><span id="more-129"></span></p>

<h2>template file:  ./base.html</h2>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;

&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

&lt;title&gt;{% block pagetitle %}Page title{% endblock %}&lt;/title&gt;


&lt;link rel=&quot;stylesheet&quot; href=&quot;&quot; type=&quot;text/css&quot; media=&quot;screen&quot; /&gt;
{% block head %}

{% endblock %}

&lt;/head&gt;
&lt;body&gt;
{% block body %}

{% endblock %}
&lt;/body&gt;
&lt;/html&gt;
</pre>


<h2>template file: ./blog/index.html</h2>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
{% extends &quot;base.html&quot; %}

{% block title %}
    A minimal blog, powered by Django
{% endblock %}

{% block body %}
&lt;h2&gt;Hello, world!&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;./add&quot;&gt;Write new post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

{% for post in posts %}
&lt;div class=&quot;post&quot;&gt;
    &lt;h2&gt;&lt;a href=&quot;./{{ post.slug }}.html&quot; title=&quot;{{ post.title }}&quot;&gt;
        {{ post.title }}&lt;/a&gt;&lt;/h2&gt;
    &lt;div class=&quot;postmeta&quot;&gt;
        &lt;div class=&quot;postdate&quot;&gt;{{ post.pub_date }}&lt;/div&gt;
        &lt;div class=&quot;posttags&quot;&gt;
        Tags: 
        {% for tag in post.tags.all %}
            {{ tag.tag }},
        {% endfor %}
        &lt;/div&gt;
        &lt;div class=&quot;postauthor&quot;&gt;
            By {{ post.author }}.
        &lt;/div&gt;
    &lt;/div&gt;&lt;!-- end postmeta --&gt;
    &lt;a href=&quot;./edit/{{ post.id }}&quot;&gt;Edit post&lt;/a&gt;
    &lt;div class=&quot;postcontent&quot;&gt;
    {{ post.content }}
    &lt;/div&gt;
&lt;/div&gt;

{% endfor %}
{% endblock %}
</pre>


<h2>template file: ./blog/editpost.html</h2>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
{% extends &quot;base.html&quot; %}

{% block title %}
        Add post
{% endblock %}

{% block body %}
&lt;h2&gt;Write a post&lt;/h2&gt;
&lt;form method=&quot;POST&quot; action=&quot;.&quot;&gt;
        {{ form.as_p }}

        &lt;input type=&quot;submit&quot; value=&quot;submit&quot; /&gt;
&lt;/form&gt;

{% endblock %}
</pre>


<h2>models.py</h2>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# Models for django blog application

from django.db import models

class Tag(models.Model):
    tag = models.CharField(maxlength=50)  # tagname

    def __str__(self):
        return self.tag

    class Admin:
        pass

class Author(models.Model):
    name = models.CharField(maxlength=100)
    email = models.EmailField()

    def __str__(self):
        return self.name

    class Admin:
        pass

class Article(models.Model):
    title = models.CharField(maxlength=250)
    slug = models.CharField(maxlength=250)
    content = models.TextField()
    author = models.ForeignKey(Author)
    pub_date = models.DateTimeField('date published')
    mod_date = models.DateTimeField('date modified')
    tags = models.ManyToManyField(Tag)

    def __str__(self):
        return self.title

    class Admin:
        pass
</pre>


<h2>url.py</h2>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    # Example:
    # (r'^djangotest/', include('djangotest.foo.urls')),

    (r'^blog/$', 'djangotest.blog.views.index'),

    #  regex for slugs.  Note that the regex matches even 
    #  .html without slug:  this gets handled in views.single
    (r'^blog/(?P&amp;lt;slug&amp;gt;((\w+|-)*))(\.html)\/?$', 'djangotest.blog.views.single'),

    # edit post
    (r'^blog/edit/(?P&amp;lt;post_id&amp;gt;\d+)/$', 'djangotest.blog.views.edit'),   

    # add new post
    (r'^blog/add/$', 'djangotest.blog.views.edit'),

    # Uncomment this for admin:
    (r'^admin/', include('django.contrib.admin.urls')),
)
</pre>


<h2>views.py</h2>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# -*- coding: utf-8 -*-
# views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.template import Context, loader
from django.shortcuts import render_to_response, get_list_or_404

from django import newforms as forms
from django.newforms.widgets import *

from djangotest.blog.models import *

def index(request):
    &quot;&quot;&quot; Display last 5 articles &quot;&quot;&quot;
    # TODO:  make '5' not a magic number
    last_five = Article.objects.all().order_by('-pub_date')[:5]

    t = loader.get_template('blog/index.html')
    c = Context({
        'posts' : last_five,
    })

    return HttpResponse(t.render(c))


def single(request, slug):
    # handle page not found
    articles = get_list_or_404(Article, slug__exact=slug)
    return render_to_response('blog/index.html', { 'posts':articles })

def edit(request, post_id=None):

    if post_id is None:
        # no id, user is creating new post
        ArticleForm = forms.models.form_for_model(Article)
    else:
        # editing or updating post
        try:
            article = Article.objects.get(id=post_id)
        except Article.DoesNotExist:
            HttpResponseRedirect('blog/postdoesnotexist.html')

        ArticleForm = forms.models.form_for_instance(article)

    # we need to feed the new widget with the choices from the 
        # default one:  SelectMultiple

    ArticleForm.base_fields['tags'].widget = CheckboxSelectMultiple(
        choices=ArticleForm.base_fields['tags'].choices)
    ArticleForm.base_fields['author'].widget = RadioSelect(
        choices=ArticleForm.base_fields['author'].choices)

    if request.method == 'POST':
        # form has been submited (i.e., new post or old post update)
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/blog')

    else:
        # empty form
        form = ArticleForm()

    return render_to_response('blog/editpost.html', { 'form': form })
</pre>


<h2>References</h2>

<ul>The following pages were of great help in understanding the newforms library better:
<li>The Django <a href="http://www.djangoproject.com/documentation/newforms/" target="_blank">documentation for newforms</a>. (Still work in progress.)</li>
<li>Some examples of using a select field with static choices and hidden fields: <a href="http://weblog.bignerdranch.com/?p=31" target="_blank">Big nerd ranch</a>. (qué tal nombre&#8230;)</li>
<li>How to render <a href="http://eggdrop.ch/blog/2007/02/15/django-dynamicforms/" target="_blank">dynamic forms using Django newforms</a>.  From the author&#8217;s blog:  <em>the newforms library works only for static forms. Forms that have a fixed number of fields. What I wanted to do, is create a page that allows you to edit multiple instances of a model at once.</em>.  Uses Javascript, no AJAX.</li>
<li>How to use the <a href="http://unpythonic.blogspot.com/2007/01/django-newforms-for-models.html" target="_blank">model specified defaults as the default values for fields</a>, and how to make the help_text entries available in the fields for rendering.</li> 
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Iterating over items of selection fields in django templates using newforms</title>
		<link>http://www.zoia.org/blog/2007/03/24/iterating-over-items-of-selection-fields-in-django-templates-using-newforms/</link>
		<comments>http://www.zoia.org/blog/2007/03/24/iterating-over-items-of-selection-fields-in-django-templates-using-newforms/#comments</comments>
		<pubDate>Sat, 24 Mar 2007 16:28:33 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[checkboxes]]></category>
		<category><![CDATA[newforms]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[templates]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2007/03/24/iterating-over-items-of-selection-fields-in-django-templates-using-newforms/</guid>
		<description><![CDATA[A year ago I wrote a custom CheckboxSelectMultiple control for django. My application needed to display a series of checkboxes on the webpage, but the default django control did not allow iteration over each checkbox when the control was rendered in the template (as it was possible with the RadioSelect control). This finer control was [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>A year ago I wrote a <a href="http://www.zoia.org/blog/2006/02/22/django-and-custom-checkboxselectmultiplefield/">custom CheckboxSelectMultiple</a> control for <a href="http://www.djangoproject.com">django</a>.  My application needed to display a series of checkboxes on the webpage, but the default django control did not allow iteration over each checkbox when the control was rendered in the template (as it was possible with the RadioSelect control).  This finer control was necessary because I needed to insert extra HTML between each checkbox.</p>

<p>As of version 0.95, django has been under heavy changes, and my custom control no longer works.  In particular, the old forms module is being discarded in favor of the newforms module that will become the default forms module sometime in the future.  A good explanation can be found in the on-site django documentation, under <a href="http://www.djangoproject.com/documentation/newforms/#migration-plan">newforms-migration plan</a>.</p>

<p>The good news is that newforms allows access to individual items of the form fields, multiple-select fields included. The newforms documentation is still work in progress, so it took me a while to figure out how to do it&#8230; by inspecting the source code and regression tests. It seems pretty obvious now, should have asked in the <a href="http://groups.google.com/group/django-users">django-users list</a>.</p>

<p>The example code has been tested with django svn release 4812 (2007-3-23).</p>

<p><strong><span style="text-decoration: underline;">2007-03-27</span></strong>: By mistake I published an incorrect version of <code>views.py</code>.  Code has been corrected so that now   <code>add_post</code> saves the tag field as expected. <span style="text-decoration: line-through;">(<code>Post</code> has a many-to-many relationship with <code>Tag</code>, so <code>form.save()</code> is not enough to save the form data.)</span></p>

<p><strong><span style="text-decoration: underline;">2007-04-12</span></strong>:  The code for <code>views.py</code> has been corrected again.  The code posted 2007-03-27 works, but as I discovered later, there is no need to create another object (<code>p = Post(**cleandata)</code>) to handle the many-to-many field data.  <code>form.save()</code> takes care of everything, as expected.</p>

<p><strong><span style="text-decoration: underline;">2007-04-24</span></strong>:  You may be interested in <a href="http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/">this post</a>.</p>

<h2>template</h2>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
&lt;ul&gt;
{% for choice in form.base_fields.tag.choices %}
&lt;li&gt; ({{ choice.0 }}, {{ choice.1 }}) &lt;/li&gt;
{% endfor %}
&lt;/ul&gt;

</pre>


<h2>models.py</h2>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# -*- coding: utf-8 -*-
# models.py

from django.db import models

class Tag(models.Model):
    tag = models.CharField(maxlength=20)

    def __str__(self):
        return self.tag

class Post(models.Model):
    # other fields here:
    # text = models.CharField(maxlength=255)
    # title = models.CharField(maxlength=50)
    # etc.
    tag = models.ManyToManyField(Tag)

</pre>


<h2>views.py</h2>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# -*- coding: utf-8 -*-
# views.py

from django.template import Context, loader
from django.http import HttpResponse, HttpResponseRedirect

from django import newforms as forms
from django.newforms.widgets import *

from project.models import *

def add_post(request):
    postForm = forms.models.form_for_model(Post)
    if request.method == 'POST':
       form = postForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(&quot;/&quot;)
    else:
         form = postForm()
         t = loader.get_template('add_post.html')
         c = Context({
               'form': form,
               })
        
         return HttpResponse(t.render(c))
</pre>


<h2><span style="text-decoration: line-through;">views.py</span></h2>

<p>This is an old version of <code>views.py</code>.  The code works, but as I discovered later, there is no need to create another object (<code>p = Post(**cleandata)</code>) to handle the many-to-many field data.  form.save() takes care of everything, as expected.</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
# -*- coding: utf-8 -*-
# views.py

from django.template import Context, loader
from django.http import HttpResponse, HttpResponseRedirect

from django import newforms as forms
from django.newforms.widgets import *

from project.models import *

def add_post(request):
    postForm = forms.models.form_for_model(Post)
    if request.method == 'POST':
        form = postForm(request.POST)
        if form.is_valid():
           cleandata = form.clean_data
           # use the form tag ids to select the Tag instances
           # related to this Post entry
           tag = Tag.objects.in_bulk(cleandata['tag'])
           # need to delete the tag ids from clean data,
           # otherwise p = Post(** cleandata) will complain that
           # tag is not a parameter of Post( )
           del cleandata['tag']

           # create an instance of Post from the form data
           p = Post(**cleandata)
           p.save()   # need to save so p gets an id.
           p.tag = tag
           p.save()

           return HttpResponseRedirect(&amp;quot;/&amp;quot;)
       else:
       form = postForm()

       t = loader.get_template('add_post.html')
       c = Context({
              'form': form,
        })

        return HttpResponse(t.render(c))
</pre>

]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2007/03/24/iterating-over-items-of-selection-fields-in-django-templates-using-newforms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo correr Django (y Python) usando Apache y FastCGI</title>
		<link>http://www.zoia.org/blog/2006/12/16/como-correr-django-y-python-usando-apache-y-fastcgi/</link>
		<comments>http://www.zoia.org/blog/2006/12/16/como-correr-django-y-python-usando-apache-y-fastcgi/#comments</comments>
		<pubDate>Sun, 17 Dec 2006 01:55:29 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/2006/12/16/como-correr-django-y-python-usando-apache-y-fastcgi/</guid>
		<description><![CDATA[Resumo en este post como hacer funcionar Django en un servidor Linux con CentOS 4.4 usando Apache 2 y FastCGI. Estas cosas están dispersas en Internet, la principal finalidad del post es tenerlas juntas en algún sitio. Por qué FastCGI y no mod_python Es la primera pregunta que uno se hace: si mod_python funciona, para [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Resumo en este post como hacer funcionar  <a href="http://www.djangoproject.com">Django</a> en un servidor Linux con CentOS 4.4 usando <a href="http://httpd.apache.org">Apache 2</a> y <a href="http://www.fastcgi.com">FastCGI</a>.  Estas cosas están dispersas en Internet, la principal finalidad del post es tenerlas juntas en algún sitio.</p>

<h2>Por qué FastCGI y no mod_python</h2>

<p>Es la primera pregunta que uno se hace:  si mod_python funciona, para qué quieres usar <a href="http://www.fastcgi.com">FastCGI</a>.  No es porque <em>fastcgi</em> vuelve a estar de moda, por supuesto.
El problema <em>real</em> es que mod_python y mod_php no se llevan bien, y de hecho en CentOS 4.4, usando mod_php, MySQL y mod_python, este último no funciona. <a href="http://www.modpython.org/pipermail/mod_python/2005-May/018166.html">Aquí</a> y aquí (<a href="http://www.djangoproject.com/documentation/modpython/">If you get a segmentation fault</a>) se explican las posibles causas.  Al parecer tiene que ver con el hecho de Apache usa la librería expat del sistema (y la precarga cuando se inicia el servidor de web), mientras que mod_python usa la versión de expat que fue compilada en la distribución de Python que tenga el sistema operativo.  Si las dos versiones no coinciden, se produce un segmentation fault.   También puede deberse a un cruce similar entre las librerías de MySQL, mod_php y mod_python, pero el resultado final es similar. 
En los dos casos Apache sigue corriendo y mod_python se reinicia, pero nuestro programa en Python no se ejecuta.  El segfault queda registrado en el log de errores de Apache (<code>/var/log/httpd/error_log</code> o algún lugar cercano, dependiendo de esté instalado Apache) y el navegador queda en blanco.<br />
Y por eso la necesidad de usar fastcgi para correr Django.
<span id="more-82"></span></p>

<h2>Algunas consideraciones preliminares</h2>

<ul>
<li>El sistema en el que he hecho la instalación es un servidor con CentOs 4.4 y Python 2.3.4. (Al parecer no hay modo fácil de actualizar el Python del CentOs a 2.5 o por lo menos a 2.4 sin que se rompan muchas cosas).  Estamos usando Apache2.</li>
<li>Se supone que este servidor ya tiene Django instalado, y que nuestra aplicación no tiene problemas con el servidor de desarrollo que trae Django.  (Esto no es un tutorial de Django&#8230; la documentación de Django explica perfectamente como instalarlo).</li>
<li>Si buscamos un poco en Google, muchas páginas insisten en que si queremos instalar fastcgi y python, necesitamos instalar una librería de python llamada <em>flup</em>;  y, si la versión de python es 2.3 o menor, también necesitamos instalar una librería llamada <em>eunuchs</em>.  Porque a Python 2.3 le falta algo&#8230; la capacidad de escribir <em>socket pairs</em>, un tema que no viene al caso ahora. 
Bien, si lo que queremos es instalar Django, <em>ninguna de estas dos librerías es necesaria</em>.  Django, a partir de la versión 0.95, trae su propia implementación de <em>flup</em>, y no necesita instalar <em>eunuchs</em>.</li>
</ul>

<h2>Aclarémonos dónde están las cosas</h2>

<p>Estamos instalando django con la siguiente configuración, quizá no muy usual:</p>

<ul>
<li>El <code>DocumentRoot</code> de nuestro servidor Apache es <code>/var/www/html</code>.</li>
<li>El directorio con el proyecto de Django es <code>/home/django/prog</code>.</li>
<li>El directorio con los archivos .css, imágenes, y demás que necesitan las páginas web es, para el proyecto de Django, <code>/home/django/progmedia</code>.</li>
<li>El archivo <code>settings.py</code> está en <code>/home/django/prog/settings.py</code>, que es lo normal.</li>
<li>Se accede a nuestro programa a través del URL <code>http://example.com/prog</code>.</li>
</ul>

<h2>Instalar FastCGI</h2>

<ul>
<li>FastCGI es un módulo de Apache que no viene con la distribución de Apache.  Es necesario descargarlo del website de fastcgi: <a href="http://www.fastcgi.com">http://www.fastcgi.com</a>.  </li>
<li>Las instrucciones sobre cómo compilar e instalar este módulo están muy claras en el archivo INSTALL.AP2 que viene con las fuentes de fastcgi.  Pero (siempre hay un pero) lo que no dice el INSTALL.AP2 es que necesitamos además los paquetes de desarrollo de apache:  <code>httpd-devel</code> y sus requisitos (<code>apr-devel</code> y <code>apr-util-devel</code>).  Podemos decir # rpm -qa httpd* para averiguar si los headers de desarrollo están o no instalados en nuestro servidor.  Si es necesario, los instalamos con yum: <code># yum install httpd-devel</code>.</li>
<li>Para <em>fastcgi</em> con CentOS es necesario usar la opción <code>top_dir</code>, porque por defecto <em>fastcgi</em> (como debe ser) trata de instalarse en <code>/usr/local/lib</code> en vez de en <code>/usr/lib</code>.</li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">$ make top_dir=/usr/lib/httpd</pre>


<ul>
<li>Si la compilación terminar sin errores, instalamos <em>fastcgi</em> con el comando</li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate"># make top_dir=/usr/lib/httpd install
</pre>

<ul>
<li>(<a href="http://bliki.rimuhosting.com/space/knowledgebase/linux/webserver/apache/installing+and+using+mod_fastcgi">credit where credit is due</a>) <em>fastcgi</em> necesita un directorio para escribir datos de sus transacciones, pero no puede escribir a <code>/var/log/httpd/fastcgi</code>, la opción por defecto, aunque este directorio tenga permisos 777 y sea propiedad de apache:apache.  Según dicen los mitos tiene algo que ver con el manejo de symlinks dentro de fastcgi. En el <code>error_log</code> de Apache aparece:  <code>[crit] (13)Permission denied: FastCGI: can't create (dynamic) server "/var/www/html/prog.fcgi": bind() failed [/var/log/httpd/fastcgi/dynamic/abcdef01020304]</code>
La solución es crear un directorio en /tmp:</li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
# mkdir -p /tmp/fcgi/dynamic
# chown apache:apache -R /tmp/fcgi
# chmod 755 -R /tmp/fcgi
</pre>


<ul>
<li>Ahora hay que decirle a Apache que queremos usar el módulo fastcgi que acambamos de instalar.  Creamos el archivo <code>/etc/httpd/conf.d/fastcgi.conf</code>:</li>
</ul>

<pre>
</pre><pre class="brush: bash; title: ; notranslate">
LoadModule fastcgi_module modules/mod_fastcgi.so

&lt;IfModule mod_fastcgi.c&gt;;
    # Tenemos que decirle a fastcgi dónde puede guardar la información de sus conexiones, porque
    # no estamos usando el directorio por defecto.
        FastCgiIpcDir       /tmp/fcgi/

    # Asociamos los archivos de extensión .fcgi a fastcgi 
        AddHandler      fastcgi-script .fcgi
&lt;/IfModule&gt;
</pre>


<ul>
<li>Recargamos la configuración de Apache y vemos en el <code>/var/log/httpd/error_log</code> si todo ha ido bien. </li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
# tail -f /var/log/httpd/error_log 
</pre>


<p>(esta ventana se pude quedar abierta hasta que estemos seguros que el fastcgi funciona y bien)</p>

<p>En otra ventana:</p>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
# service httpd reload
</pre>


<h2>RewriteEngine y ExecCGI</h2>

<ul>
<li>Para poder usar el <code>RewriteEngine</code> en el directorio raíz (más abajo se explica para qué lo necesitamos), añadimos la opción <code>FileInfo</code> a la directiva AllowOverride del directorio raíz del servidor web.</li>
<li>También queremos ejecutar programas usando fastcgi en el directorio raíz del servidor de web. (repetimos: <em>en el directorio raíz del servidor de web</em>, el <code>DocumentRoot</code>, no en el directorio en el que está nuestro proyecto Django). Para eso, modifico <code>/etc/httpd/conf/httpd.conf</code></li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
#
&lt;Directory &quot;/var/www/html&quot;&gt;
# 
# (... aquí he borrado los comentarios)
#
#  Añadimos ExecCGI a las opciones

     Options Indexes FollowSymLinks IncludesNoExec &lt;strong&gt;ExecCGI&lt;/strong&gt;

# (... más comentarios)
# Añado el FileInfo para que me deje usar mod_rewrite en /home/www

     AllowOverride AuthConfig &lt;strong&gt;FileInfo&lt;/strong&gt;
</pre>


<p>Nuevamente recargo Apache y veo en el <code>error_log</code> si todo va bien.</p>

<h2>Un puente entre Apache y Python</h2>

<ul>
<li>Ahora necesitamos un puente (está bien, un proxy&#8230;)  que permita a fastcgi comunicarse con nuestro programa en Python.  Para suerte nuestra, alguien ya escribió ese puente:  <code>fcgi.py</code>. </li>
<li>Descargamos el módulo fcgi.py de internet.  Ojo que si buscamos en Google hay dos resultados:  uno es el módulo de Robin Dunn (el mismo de <a href="http://www.wxpython.org">wxPython</a>), y otro en el website de Saddi Enterprises. Este último es el que nos interesa: <code>http://svn.saddi.com/py-lib/trunk/fcgi.py</code>.</li>
<li>Copiamos <code>fcgi.py</code> a la raíz del servidor web, cambiarmos propietario a apache y nos aseguramos de que apache pueda leer el archivo:</li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
# cp fcgi.py /var/www/html
# chown apache:apache /var/www/html/fcgi.py
# chmod 755 /var/www/html/fcgi.py
</pre>


<ul>
<li>Una vez que tenemos la herramientas, ahora hay que construir el puente.  Creamos el siguiente script (sacado del website de Django), que es el que, usando las funciones de <code>fcgi.py</code>, hace realmente de proxy entre fastcgi y nuestro proyecto Django. Lo guardo en el directorio raíz del servidor de web con el nombre <code>prog.fcgi</code>. (Volvemos a repetir:  lo guardamos en la raíz del servidor de web, no en la raíz del directorio de nuestro proyecto).</li>
</ul>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
#!/usr/bin/python

import sys, os

# Add a custom system path
sys.path.insert(0,&quot;/home/django&quot;)

# switch to user project
os.chdir(&quot;/home/django/prog&quot;)
os.environ['DJANGO_SETTINGS_MODULE'] = &quot;prog.settings&quot;

from fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler

WSGIServer(WSGIHandler()).run()
</pre>


<ul>
<li>Idem, le cambio el propietario y permisos para que pueda ser ejecutado por Apache.</li>
</ul>

<pre>
</pre><pre class="brush: bash; light: true; title: ; notranslate">
# chown apache:apache /var/www/html/prog.fcgi
# chmod 755 /var/www/html/prog.fcgi
</pre>


<h2>Rewrite rules</h2>

<p>Como dice el manual de Apache, &#8221;Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo.&#8221; &#8212; Brian Moore, bem@news.cmc.net</p>

<p>A continuación vamos a escribir unas reglas (&#8221;Rewrite rules&#8221;) de modo que cuando el usuario escriba el URL de nuestro programa en el navegador, Apache realmente redireccione la llamada al script <code>prog.fcgi</code>que acabamos de escribir.  Este script, a su vez, llamará al programa escrito con Django en <code>/home/django/prog</code>.<br />
Explico esto en detalle porque aunque al final el resultado sea solamente dos o tres líneas en un archivo de configuración, si no entendemos qué estamos haciendo, después tendremos problemas&#8230; causados por nosotros mismos.</p>

<ul>
<li><p>Dentro del programa en Django, los distintos añadidos al URL a la derecha de sccr/ sirven para direccionar al usuario, a través del módulo urls.py, a las distintas partes de nuestro programa.  Por ejemplo,</p>

<pre><code>http://example.com/prog/admin

http://example.com/prog/correo

</code></pre></li>
<li><p>Lo que necesitamos es que Apache pase todos esos añadidos (<code>prog</code> incluido) al módulo <code>prog.fcgi</code>, que se encargará a su vez de reenviarlo a nuestro programa de modo transparente:  el programa nunca sabrá si fue llamado a través de mod_python, con el servidor de desarrollo del mismo Django, etc. (de acuerdo, probablemente sí hay forma de que lo sepa&#8230; pero a los efectos que nos interesan, no lo sabe).</p>

<pre><code>http://tierramedia.oficinas/prog.fcgi/prog/admin/

http://tierramedia.oficinas/prog.fcgi/prog/correo/

</code></pre></li>
<li><p>Los rewrite rules se pueden poner en muchos sitios distintos.  Por ejemplo, en el archivo <code>.htaccess</code> en la raíz del servidor web:</p></li>
</ul>

<pre>
</pre><pre class="brush: bash; title: ; notranslate">
RewriteEngine On
RewriteRule ^(prog\.fcgi/.*)$ - [L]
RewriteRule ^(prog/.*)$ prog.fcgi/$1 [L]
</pre>


<p>Con estas reglas, estamos diciendo dos cosas:
* la primera: si el URL contiene la cadena <code>prog.fcgi/</code>, simplemente se pasa tal cual. La [L] quiere decir que después de esta regla no seguimos aplicando más reglas.
* la segunda: si el URL contiene la cadena <code>prog/</code>, reescribe la cadena y todo lo que le siga insertando <code>prog.fcgi/</code> por delante. Nuevamente la [L] quiere decir que después de esta regla no seguimos aplicando más reglas.</p>

<p>Como anteriormente hemos indicado a Apache en el archivo <code>fastcgi.conf</code> que toda extensión <code>.fcgi</code> en el directorio raíz debe procesarse con el módulo fastcgi, una vez reescrito el URL Apache ejecutará el script <code>sccr.fcgi</code>.</p>

<ul>
<li>Otra alternativa es crear un archivo <code>/etc/httpd/conf.d/prog.conf</code> con los <em>rewrite rules</em>:  es más eficiente que ponerlas en <code>.htaccess</code> (pero por otro lado no siempre vamos a poder modificar directamente la configuración del Apache).  En ese caso, tenemos que especificar cláramente para qué directorio son las reglas:</li>
</ul>

<pre>
</pre><pre class="brush: bash; title: ; notranslate">
&lt;Directory /var/www/html&gt;
   RewriteEngine On
   RewriteRule ^(prog\.fcgi/.*)$ - [L]
   RewriteRule ^(prog/.*)$ prog.fcgi/$1 [L]
&lt;/Directory&gt;
</pre>


<ul>
<li>Por supuesto, cada vez que cambimos la configuración necesitamos decirle a Apache que recargue los archivos de configuración:  <code># service httpd reload</code>.</li>
</ul>

<h2>Otros directorios de Django</h2>

<ul>
<li>Por último, si tenemos un directorio dentro del proyecto para el <em>media</em>, necesitamos decirle a Apache que asocie el URL con el directorio>.  Por ejemplo, <code>http://example.com/progmedia</code> con el directorio <code>/home/django/progmedia</code>. Para eso creamos o añadimos al archivo <code>/etc/httpd/conf.d/prog.conf</code>:</li>
</ul>

<pre>
Alias /progmedia /home/django/progmedia
</pre>

<p>Y listo.  Ahora deberíamos tener nuestro servidor Apache funcionando con Python, Django y FastCGI.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2006/12/16/como-correr-django-y-python-usando-apache-y-fastcgi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django and Custom CheckboxSelectMultipleField</title>
		<link>http://www.zoia.org/blog/2006/02/22/django-and-custom-checkboxselectmultiplefield/</link>
		<comments>http://www.zoia.org/blog/2006/02/22/django-and-custom-checkboxselectmultiplefield/#comments</comments>
		<pubDate>Thu, 23 Feb 2006 02:19:07 +0000</pubDate>
		<dc:creator>Roberto</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.zoia.org/blog/archives/2006/02/22/django-and-custom-checkboxselectmultiplefield/</guid>
		<description><![CDATA[Note: as of Django version 0.95, this solution no longer works. But thanks to the newforms module, it is no longer necessary. Explanation of how it works can be found in this post The problem: I have been using Django in a project for some weeks. The application needs to display a series of checkboxes [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><strong>Note</strong>:  as of Django version 0.95, this solution no longer works.  But thanks to the newforms module, it is no longer necessary.  Explanation of how it works can be found <a href="http://www.zoia.org/blog/2007/03/24/iterating-over-items-of-selection-fields-in-django-templates-using-newforms">in this post</a></p>

<p><strong>The problem</strong>:  I have been using <a href="http://www.djangoproject.org" title="Django Project">Django</a> in a project for some weeks.  The application needs to display a series of checkboxes on the webpage, but the HTML rendering of the formfields.CheckboxSelectMultipleField class does not offer the precise placement of each checkbox that is needed on the webpage.
formfields.CheckboxSelectMultipleField is a descendant of SelectMultipleField and does not provide the ability to iterate through each of the possible choices, as formfields.RadioSelectField derived objects do:</p>

<pre>
</pre><pre class="brush: xml; title: ; notranslate">
&lt;!-- choices is an formfields.RadioSelectField object 
      This is not possible with formfields.CheckboxSelectMultipleField derived objects.
--&gt;
&lt;div class=&quot;form-row&quot;&gt;
&lt;table&gt;&lt;tr&gt;
     {% for i in form.choices.field_list %}
           &lt;td&gt;;{{ i.field }}&lt;/td&gt;&lt;td&gt;{{i.name}}&lt;/td&gt;
     {% endfor %}
     &lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
</pre>


<p><strong>The Solution</strong>:  a custom CheckboxesMultipleSelectField based on the code from formfields.RadioSelectField.</p>

<p>CustomCheckboxSelectMultipleField is intended to be used in a custom Manipulator.</p>

<p>The code for the custom CheckboxSelectMultiple</p>

<pre>
</pre><pre class="brush: python; title: ; notranslate">
from django.core import formfields

class CustomCheckboxSelectMultipleField(formfields.FormField):
    def __init__(self, field_name, choices=[], ul_class='', is_required=False, validator_list=[], member_name=None):
        self.field_name = field_name
        # choices is a list of (value, human-readable key) tuples because order matters
        self.choices, self.is_required = choices, is_required
        self.validator_list = [self.isValidChoice] + validator_list
        self.ul_class = ul_class
        if member_name != None:
            self.member_name = member_name

    def render(self, data):
        &quot;&quot;&quot;
        Returns a special object that is iterable *and*
        has a default str() rendered output.

        This allows for flexible use in templates. You can just use the default
        rendering:

            {{ field_name }}

        ...which will output the radio buttons in an unordered list.
        Or, you can manually traverse each radio option for special layout:

            {% for option in field_name.field_list %}
                {{ option.field }} {{ option.label }}&lt;br /&gt;
            {% endfor %}
        &quot;&quot;&quot;

        class CustomCheckBoxSelectMultipleRenderer:
            def __init__(self, datalist, ul_class):
                self.datalist, self.ul_class = datalist, ul_class
            def __str__(self):
                &quot;Default str() output for this radio field -- a &lt;ul&gt;&quot;
                output = ['&lt;/ul&gt;&lt;ul %s&gt;' % (self.ul_class and ' class=&quot;%s&quot;' % self.ul_class or '')]
                output.extend(['&lt;li&gt;%s %s&lt;/li&gt;' % (d['field'], d['label']) for d in self.datalist])
                output.append('&lt;/ul&gt;')
                return ''.join(output)
            def __iter__(self):
                for d in self.datalist:
                    yield d
            def __len__(self):
                return len(self.datalist)

        datalist = []
        str_data_list = map(str, data) # normalize to string
        for i, (value, display_name) in enumerate(self.choices):
            checked_html = ''
            if str(value) in str_data_list:
                checked_html = 'checked=&quot;checked&quot;'
            datalist.append({
                'value': value, 'checked': checked_html,
                'name': display_name,
                'field': '&lt;input type=&quot;checkbox&quot; id=&quot;%s&quot; name=&quot;%s&quot; value=&quot;%s&quot;%s/&gt;' % \
                    (self.get_id() + '_' + str(i), self.field_name, value, checked_html),
                'label': '&lt;label for=&quot;%s&quot;&gt;%s&lt;/label&gt;' % \
                    (self.get_id() + '_' + str(i), display_name),
            })

        return CustomCheckBoxSelectMultipleRenderer(datalist, self.ul_class)

    def isValidChoice(self, data, form):
        str_data = str(data)
        str_choices = [str(item[0]) for item in self.choices]
        if str_data not in str_choices:
            raise validators.ValidationError, _(&quot;Select a valid choice; '%(data)s' is not in %(choices)s.&quot;) % {'data':str_data, 'choices':str_choices}
</pre>

]]></content:encoded>
			<wfw:commentRss>http://www.zoia.org/blog/2006/02/22/django-and-custom-checkboxselectmultiplefield/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

