[Web-SIG] Random thoughts

Ian Bicking ianb at colorstudy.com
Mon Nov 3 15:53:00 EST 2003


On Nov 3, 2003, at 2:29 PM, Gregory (Grisha) Trubetskoy wrote:
> On Mon, 3 Nov 2003, Ian Bicking wrote:
>
>> On Nov 3, 2003, at 9:07 AM, Gregory (Grisha) Trubetskoy wrote:
>>>
>>> request.form(query_overrides=1)   <-- returns both
>>> request.form.postdata()
>>> request.form.querydata()
>>
>> Seems a little long-winded.  How about request.formdata, .postdata,
>> .querydata, where .formdata is postdata+querydata?  (In practice most
>> people use the combined version)
>
> I'd say -1 on postdata and querydata, because request.postdata sounds 
> to
> me like the body of the POST and querydata sounds like the "stuff after
> question mark". The word "form" has to be in there.

Sure, I don't actually like the *data names that much.  Another name 
might be "field" -- I think in some contexts field is clearer, because 
"form" has some other concepts associated with it (method and action 
being the most obvious).

>> They could be proper dictionary-like objects.
>
> Of course. To elaborate on what I had in mind (the above, btw, has an
> error - form() cannot be both a method and an object):
>
> request.form() would return a mapping object (aka dictionary-like)
> containing both post and query data.
>
> [At this point I'd like to backtrack on my prior statement - query data
> should not override post data or vice versa, they should probably be
> combined, just like they would if there were multiple form inputs by 
> the
> same name - so perhaps we don't even need to override option at all]

I generally agree, but the implementation would be easier if one 
overrides the other, like:

def __getitem__(self, name):
     try:
         return self.query[name]
     except KeyError:
         return self.post[name]

But otherwise:

def __getitem__(self, name):
     if self.query.has_key(name):
         value = self.query[name]
         if self.post.has_key(name):
             postvalue = self.post[name]
             if isinstance(value, list):
                 if isinstance(postvalue, list):
                     return value + postvalue
                 else:
                     return value + [postvalue]
             else:
                 if isinstance(postvalue, list):
                     return [value] + postvalue
                 else:
                     return [value, postvalue]
         else:
             return value
     else:
         return self.post[name]



It's not *that* bad, but it's a little annoying.  At least it's 
complete (i.e., information neither hidden nor lost).  So I think the 
less-than-elegant implementation isn't so bad.  After all, it could be 
the simpler:

def __getitem__(self, name):
     value = self.query.getlist(name) + self.post.getlist(name)
     if not value:
         raise KeyError, "..."
     elif len(value) == 1:
         return value[0]
     else:
         return value

> In case of POST, availability of form data implies that something 
> consumes
> (reads) the request. Some people would prefer to read it themselves. A
> (first) call to form() would trigger this action, after which there
> wouldn't be anything to read. Otherwise you could read it with
> request.read().

I forget how exactly cgi works right now, Webware has tried to get this 
right but I'm not sure if it has.  I think it consumes the request body 
if it's valid data that can be parsed (maybe even in spite of the 
content-type of the request), but otherwise leaves it intact and sets 
no fields.

If it is valid data that can be parsed into fields, maybe it's not so 
bad if the body is lost, because all the information remains.  If you 
have an option to keep the data, I'd just include it in the constructor 
-- parsing it lazily (and thus throwing away the body lazily) seems 
error-prone.  If it can't be parsed into fields, then certainly it 
should be available in some other form.

--
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org




More information about the Web-SIG mailing list