Iterating over items of selection fields in django templates using newforms

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 necessary because I needed to insert extra HTML between each checkbox.

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 newforms-migration plan.

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… by inspecting the source code and regression tests. It seems pretty obvious now, should have asked in the django-users list.

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

2007-03-27: By mistake I published an incorrect version of views.py. Code has been corrected so that now add_post saves the tag field as expected. (Post has a many-to-many relationship with Tag, so form.save() is not enough to save the form data.)

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

2007-04-24: You may be interested in this post.

template

</p>

<ul>
{% for choice in form.base_fields.tag.choices %}
<li> ({{ choice.0 }}, {{ choice.1 }}) </li>
{% endfor %}
</ul>

<p>

models.py

</p>

<h1>-<em>- coding: utf-8 -</em>-</h1>

<h1>models.py</h1>

<p>from django.db import models</p>

<p>class Tag(models.Model):
    tag = models.CharField(maxlength=20)</p>

<pre><code>def __str__(self):
    return self.tag
</code></pre>

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

<p>

views.py

</p>

<h1>-<em>- coding: utf-8 -</em>-</h1>

<h1>views.py</h1>

<p>from django.template import Context, loader
from django.http import HttpResponse, HttpResponseRedirect</p>

<p>from django import newforms as forms
from django.newforms.widgets import *</p>

<p>from project.models import *</p>

<p>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("/")
    else:
         form = postForm()
         t = loader.get_template('add_post.html')
         c = Context({
               'form': form,
               })</p>

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

<p>

views.py

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

</p>

<h1>-<em>- coding: utf-8 -</em>-</h1>

<h1>views.py</h1>

<p>from django.template import Context, loader
from django.http import HttpResponse, HttpResponseRedirect</p>

<p>from django import newforms as forms
from django.newforms.widgets import *</p>

<p>from project.models import *</p>

<p>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']</p>

<pre><code>       # 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;amp;quot;/&amp;amp;quot;)
   else:
   form = postForm()

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

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

<p>


Leave a Comment

Apuntes de programación Java

En esta página he colgado los resúmenes que he ido haciendo para las clases Programación Avanzada del semestre 2006-I de la Facultad de Ingeniería de la Universidad de Piura. Son una primera versión y están escritos en tono algo informal.


Leave a Comment

Links: Java Game Programming

Se me ocurrió que podía intentar desarrollar un Tetris-clone con los alumnos del curso de Programación Avanzada.  Tetris es un juego que tiene una lógica sencilla, es adictivo, y es relativamente sencillo de implementar (por lo menos, implementar una versión no muy sofisticada).

Buscando documentación en Google sobre cómo implementar un doublebuffer mínimo-mínimo en Java, encontré esta página de Andrew Davison:  Killer Game programming in Java.   Tengo un buen número de libros de programación de juegos (la mayoría para C++) y he leído basantes artículos sobre el asunto,  y  esta página web es buena y clara y toca prácticamente todos los temas necesarios para empezar a desarrollar juegos en Java.  Cada tema está en un archivo pdf e incluye el código.


Leave a Comment