maradydd: (Default)
[personal profile] maradydd
So I've been working with Django lately, and I continue to be pleased with the preeminent saneness with which it handles the interaction between HTML and Python. Here is the latest example.

Suppose you have an HTML form that your Django backend will be processing. Give each input or select element in your form a name attribute, and whatever function you POST the form back to will receive a request.POST dictionary keyed by the name. For instance, if you have a form like this:

<form id="shopping">
  <p>
    <select name="fruit">
      <option value="apples">apples</option>
      <option value="bananas">bananas</option>
      <option value="cherries">cherries</option>
    </select>
  </p>
  <p>
    <select name="meat">
      <option value="buffalo">buffalo</option>
      <option value="moose">moose</option>
      <option value="quail">quail</option>
    </select>
  </p>
  <input type="submit" value="Submit" />
</form>


Then your receiving function will get a request.POST consisting of a dictionary with the keys fruit and meat, and the value for each will be a list containing the values that were selected. And, yes, if you give those selects the multiple attribute, turning them into multi-valued choice sets, your list will contain all values that were selected. Very handy.

But wait, there's more!

Suppose that you want to give your hypothetical shopper the ability to select more than one type of fruit or meat at a time without using multiple, so you write some DOM-manipulating javascript to dynamically add more copies of the appropriate select element as needed, giving each element a unique name. (How to do this is left as an exercise for the reader. I did it, you can too.) Suppose further that you also want to give your users the ability to specify how many units of each item they want, so you add text inputs (with appropriate input validation, of course, also left as an exercise for the reader). Give each <input type="text"> the same name as its corresponding select, and you'll get a request.POST that looks like:

{ 'fruit_0': ['4', 'cherries'], 'fruit_1': ['3', 'apples'], 'meat_0': ['1', 'buffalo'] }

(In this case I'm using subscripts in my javascript to generate distinct names. There may actually be a simpler way to do this, though I haven't hit on it yet.)

This is especially useful in the case where you have some function that you want to pass each of your (amount, item) pairs to, because then you can use the handy *args syntax, e.g. [doStuffTo(*thing) for thing in request.POST.values()]. You could also use a dictionary comprehension if you're using Python 3, you bleeding-edge hacker, you. Though I don't know if Django is compatible with Python 3 (and I doubt it, given all the backward-compatibility stuff that Python 3 breaks). That, too, is left as an exercise for the reader.

(no subject)

Date: 2008-12-14 03:54 pm (UTC)
From: [identity profile] neoliminal.livejournal.com
I wish the forms in Drupal were this good.

Does django do automatic XSS testing and sanity testing on the fields?

(no subject)

Date: 2008-12-14 08:35 pm (UTC)
From: [identity profile] maradydd.livejournal.com
XSS testing I'm not sure about, but it definitely does sanity testing on fields generated by forms created through its Forms API (http://docs.djangoproject.com/en/dev/topics/forms/?from=olddocs) (which auto-generates form fields that are tied to predefined field types, e.g. IntegerField, CharField, EmailField, &c). I think it's possible to do this "more than one field with the same name" trick using the Forms API, but I haven't quite worked out how to do that yet; it might require rolling a new Field type. (There's a ComboField type that can be constructed from multiple types of fields, but documentation on it is sparse and I'm not sure whether it can be used to generate multiple inputs or if it's just for fields that should be able to accept more than one class of input, e.g. text or numbers).

Since this form is handrolled, I'm doing input validation &c myself.

(no subject)

Date: 2008-12-14 09:54 pm (UTC)
ext_157608: (Default)
From: [identity profile] sfllaw.livejournal.com
Django automatically assumes all user-contributed content and content in your database is unsafe, when rendering a Django template: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#autoescape

As well, if provides a middleware that protects against CSRF. http://docs.djangoproject.com/en/dev/ref/contrib/csrf/

(no subject)

Date: 2008-12-15 09:31 pm (UTC)
From: [identity profile] maradydd.livejournal.com
Even more excellent. Thanks for the info!

Profile

maradydd: (Default)
maradydd

September 2010

S M T W T F S
   1234
567891011
12131415 161718
19202122232425
26 27282930  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags