Django – Custom Queryset with a Formset

My goal was to apply a custom queryset to a foreign key field. When the field is in a single model form, it was pretty clear to me how to proceed. However, when the field in question is part of a ModelFormset, I wasn’t seeing the way. Oddly enough, it came to me right before bed one night – iterate through the forms in the formset to apply the queryset to each one. Here’s how I handled each case.

In this application, there is a one-to-many relationship between Event and Rsvp, and a one-to-many between Rsvp and Seat

(snippet from views.py)

    ## build the querysets
    event_queryset = Event.futures.filter(institution=inst_id)
    person_queryset = Person.objects.filter(institution=inst_id)    

    ## create the formset
    SeatFormSet    = inlineformset_factory(Rsvp, Seat, form=SeatForm, can_delete=True, extra=3)

    ...
   
    ## instantiate the form and formset
    rsvpform      = RsvpForm(instance=rsvp)
    seatformset    = SeatFormSet(instance=rsvp)

    ## Apply the queryset to the master form
    rsvpform.fields['event'].queryset = event_queryset

    ## Apply the queryset to each form in the formset
    for form in seatformset.forms:
        form.fields['person'].queryset = person_queryset

It’s important to note that the querysets must be applied each time the form and formset are instantiated in your view code in order for the validation to work correctly.

In the for statement, I first tried iterating on the formset itself, but I was told that it was not iterable. A little perusal of the Django code for formsets showed me that the forms variable in the model was the object to use instead.

I’d love to hear your comments on this technique.

Phone Numbers From Around the World

What do you do with phone numbers?

I’ve used some different tricks to validate phone numbers in the North American format (999-999-9999), but I’ve learned that we also have invitees from Europe and other locales.  The problem I have, and I think it is a common problem, is that I need to be able to accept all possible phone number formats while attempting to validate the format used.  The goal of course is to minimize entry mistakes by the users.

I would love to hear your thoughts in the comments.

Using the Python iCalendar Library

An application I’m working on uses the icalendar library (http://codespeak.net/icalendar/) to generate an ICS file of upcoming events that can be linked to another calendar program (I’ve tried Outlook and Google Calendar). One problem I was having was that I was unable to generate time zone aware times. Mine were all naive – also called ‘floating’ times – that would appear the same regardless of the calendar program’s timezone.

What I was trying to do was to create a new time zone in the ICS file, and then append the TZID parameter to each date/time value. It was not happening.

So, I dug into the source code for icalendar. This library is well documented with tests, and I soon found a solution – include a tzinfo value when supplying the date/time and icalendar will convert it to UTC and append a ‘Z’ to the end of the time to indicate this. icalendar supplies a class called LocalTimezone that can be used for this purpose. I tried it, and it worked! Here’s a simplified version of my code:

    from icalendar import Calendar, Event
    from datetime import datetime 
    from icalendar import LocalTimezone   
    
    cal = Calendar()
    
    cal.add('version', '2.0')
    cal.add('prodid', '-//test file//example.com//')
    cal.add('X-WR-CALNAME','Test Calendar ' )
    
    lt = LocalTimezone() # we append the local timezone to each time so that icalendar will convert
                         # to UTC in the output
    
    for ent in queryset:        
        event = Event()
        event.add('summary', ent.event_name)
        event.add('dtstart', datetime.combine(ent.event_date,ent.start_time).replace(tzinfo=lt))
        event.add('dtend', datetime.combine(ent.stop_date,ent.stop_time).replace(tzinfo=lt))
        event.add('dtstamp', ent.updated_on.replace(tzinfo=lt))
        event['uid'] = ent.pk  # should probably use a better guid than just the PK
        event.add('priority', 5)
        
        cal.add_component(event)
    
    return cal

And this is a sample event from the output:

BEGIN:VEVENT
DTEND: 20100714T184500Z
DTSTAMP:20100714T185936Z
DTSTART:20100719T174500Z
PRIORITY:5
SUMMARY:Gateway Production
UID:66
END:VEVENT

Note that my 1:45pm event in the US Eastern time zone (EDT) shows as 1745 in UTC.

Custom Widget – My First Experience

I hadn’t needed to write a custom widget before today, but I needed to have disabled options included in a <select> list. After a little research and a LOT of trial and error, this is what I came up with.

from django.forms.widgets import Select, force_unicode, flatatt, escape, mark_safe, chain, conditional_escape

class SelectDisabled(Select):
    def __init__(self, attrs=None, choices=(), disabled=[]):
        super(SelectDisabled, self).__init__(attrs, choices)
        self.disabled = list(disabled)

    def render(self, name, value, attrs=None, choices=()):
        if value is None: value = ''
        final_attrs = self.build_attrs(attrs, name=name)
        output = [u'<select%s>' % flatatt(final_attrs)]
        options = self.render_options(choices, [value], self.disabled)
        if options:
            output.append(options)
        output.append('</select>')
        return mark_safe(u'\n'.join(output))

    def render_options(self, choices, selected_choices, disabled_choices):
        def render_option(option_value, option_label):
            option_value = force_unicode(option_value)
            option_label = (option_value in disabled_choices) and (force_unicode(option_label) + ' - SOLD OUT') or force_unicode(option_label)
            selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
            disabled_html = (option_value in disabled_choices) and u' disabled="disabled"' or ''
            return u'<option value="%s"%s%s>%s</option>' % (
                escape(option_value), selected_html, disabled_html,
                conditional_escape(option_label))
        # Normalize to strings.
        selected_choices = set([force_unicode(v) for v in selected_choices])
        disabled_choices = set([force_unicode(v) for v in disabled_choices])
        output = []
        for option_value, option_label in chain(self.choices, choices):
            if isinstance(option_label, (list, tuple)):
                output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
                for option in option_label:
                    output.append(render_option(*option))
                output.append(u'</optgroup>')
            else:
                output.append(render_option(option_value, option_label))
        return u'\n'.join(output)

And here’s how I used it in the form:

class B2CRegistrationStartForm(Form): 
    def __init__(self, disabled, *args, **kwargs):
        super(B2CRegistrationStartForm, self).__init__(*args, **kwargs)
        if disabled:
            self.fields['event'].widget.disabled = disabled
    event = ModelChoiceField(widget=SelectDisabled(),queryset=Event.b2c_web_reg.all(),empty_label=None)  

And here is the form creation in views.py:

    disabled = []
    for e in Event.b2c_sold_out.values_list('id'):
        disabled.append(e[0])
    form = B2CRegistrationStartForm( data=request.POST or None, disabled=disabled)

(The list of disabled IDs needs to be in a list, not a list of tuples)

It works fine, and I learned about custom widgets, but I don’t feel like I was very Object Oriented in my approach. The __init__() method uses super() well, but the other two basically replace the methods in the parent class. When I update to a newer version of Django (from the current 1.0.4), I’ll have to check this carefully and probably redo it.

Anyone have suggestions on how I could better implement this feature?

Simple Search in Django

I started programming (in BASIC, Pascal, and COBOL) before the Web was available, and it’s amazing to see how much the craft has changed with instant access to thousands of references. However, sometimes I throw up a search and get back the perfect solution, and I’m frustrated that I couldn’t figure out something so simple. It’s just too easy to search instead of think.

My example today is an easy search in Django. I have read about Haystack, Solr, and other search engines that require a daemon, special database structures, and other special things, but these are overkill for a search on a relatively small dataset.

My search returned this post from Toast Driven that outlined a way to append together a few Q objects to return a search result that uses multiple terms and multiple fields. Genius!

Thanks to Daniel at Toast Driven.

Apple Sucks!

(a little side rant that I had to get out)

My iPhone has always on Internet access. Also, I am required to setup an account with Apple to even run iTunes in order to copy files to my iPhone.

So, with the potential of storing my settings and information in three places (phone, laptop, cloud), why is the only copy of these settings that I can use on the laptop?

I can’t figure out why I need a laptop at all. Why can’t the phone connect to the iTunes service directly to ‘sync’. Nope, podcast subscriptions and music (unless I purchase a song) have to be copied to the laptop first, and then copied through a little wire to the phone. Very 20th century.

Yesterday, I was trying to switch to a new computer for my syncing and downloading, and it was not easy. Just plugging in the phone didn’t work, as it wanted to overwrite the phone contents with the data in the new iTunes installation – AN EMPTY ONE THAT I HAD JUST INSTALLED! Plus, it wanted to erase my existing music, podcasts, and videos from the phone! Why can’t I copy the phone info into the new iTunes? Or a least leave it alone? Why aren’t my settings, information, subscriptions, etc., saved to and accessible from the cloud?

A quick web search found many procedures to try when transferring to a new computer, but none were easy, and I doubt if most users would be able to do it. I’ll figure it out tonight, but from a company that values design and ease of use, this is an abomination.

The Big Picture

Part 1 of 2 posts discussing my plans for an application. In this installment, I talk about phases of development and the approach to take.

My project is actually a collection of several separate, but related applications, and all share some common data elements. The conventional wisdom would be to develop the central functions first, and then bolt-on the peripheral applications after. However, real life often calls on us to do things the hard way. One of the add-on programs is needed in three months, while the basic system need is not urgent.

The central function is currently provided by an older, difficult to support application. It provides enough functionality to get the job done, but isn’t complete. Extending this system to provide the new features is unwarranted for a couple of reasons. First, the development environment (language, database, etc.) is outdated, and I have no one on staff that can work quickly in that language. Second, the platform on which it is deployed is a little shaky and certainly doesn’t meet modern expectations for scalability and security. In other words, we’re going to have to replace it more likely sooner than later, and we will have a tough time supporting it until then.

So with that background, here is my dilemma. As I work on the peripheral application, how much should I worry about later integration with the central system? I certainly don’t have the time to develop all of the central functionality needed, which would basically require that I design and write the central application. Creating what would be a stand-alone application for this peripheral would be quicker, but the integration work later would be extensive.

I’m reminded of a bridge that was built near my house. The big plan calls for a major highway to be built connecting this bridge to a new route around the city. But the construction (or even the funding plans) for this new highway hadn’t started, and there was no clear idea when or if it would. So, an approach that connected the bridge to an existing road was built, even though it would have to be torn out when the new highway came through. Now, nine years a later, the new highway is still a dream, while the bridge gets much traffic. It would have been a shame to leave it either unconnected or poorly connected to the highway grid for this long.

My plan calls for a (mostly) independent development of this add-on application. I will take the bigger picture into account when laying out the data structures, but I am not going to worry about writing all of the functionality in a generic way that will work in all cases. Focus will be on the current goal.

When it comes time to connect to the central application, some rewrite will be necessary, but my users will have a solid system to use in the mean time.

What do you think? Am I on the right track, or am I heading for big troubles down the road? Please leave your comments below.

Didn’t Expect That

Had an invitee drop us a note the other day to tell us that she was frustrated that she wasn’t able to indicate that she would not be attending. A second person invited to the same event accepted the invitation, only to mention in the notes that she couldn’t make it.

I hadn’t thought about including a decline option on a registration site, but it’s been added to the feature list for the future.

Full URL in Django

The application I’m developing includes an XML feed, in which one of the items is a URL Unfortunately, using the {% url %} tag in the template only gives the path portion of the URL. Time for a little research.

Many web posts pointed me to the Sites framework included with Django, as it can return the domain for the site. I tried it out, and it worked, but I didn’t like how it would have to be implemented in my multiple server scenario (laptop, DEV server, QA server, Production). Each would have to have any entry in the sites table, and the SITE_ID in the settings.py file for each instance would have to point to the correct entry. This would be awkward at best, and would limit the possibility of making the application reusable.

A couple of bloggers mentioned using RequestSite instead. It shares the same API with the Sites class, but doesn’t use the sites table. Instead, the domain name is pulled from the request object. Here’s a sample of the view logic:

   from django.contrib.sites.models import RequestSite    
    site_name = RequestSite(request).domain
    
    return render_to_response('template.xml', 
                              {'entries': queryset, 'site_name' : site_name}, 
                              context_instance=RequestContext(request), 
                              mimetype='text/xml')

After pulling the domain from the request, it is passed along to the template in the context dictionary. In the template, I can reference the variable ‘site_name‘ in front of the {% url %} tag. However, before I have a full URL, I also need to know the protocol.

Another blog post demonstrated the is_secure attribute of the request object. Testing this attribute can help us determine is the protocol is http or https. The temple code for a full URL is:

{% if request.is_secure %}https{% else %}http{% endif %}://{{ site_name }}
{% url entry e.pk %}

Maybe a little clumsy, but it gets the job done without hard coding anything.

I’d love to hear your thoughts in the comments.

Is Short Sweet?

I was reading this post by Jacob Kaplan-Moss on Dynamic Form Generation, and this little side point caught my interest. He pointed out a more compact way to write a view for a create operation.

OLD WAY:

from django.shortcuts import redirect, render_to_response
from myapp.forms import UserCreationForm

def create_user(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            do_something_with(form.cleaned_data)
            return redirect("create_user_success")
    else:
        form = UserCreationForm()

    return render_to_response("signup/form.html", {'form': form})

NEW WAY:

def create_user(request):
    form = UserCreationForm(request.POST or None)
    if form.is_valid():
        do_something_with(form.cleaned_data)
        return redirect("create_user_success")

    return render_to_response("signup/form.html", {'form': form})

Now, I’m all for keeping things concise, but I’m not sure if this new way is as clear. I want to keep my code readable for those that are tasked with maintaining it someday can understand it.

What do you think? Is the 2nd method OK when others need to read the code?