OK, in the scheme of things, this is really minor, but it irks me. Wouldn’t it have been great if the query component of a URL started with an ampersand instead of a question mark?
How many times do we have to write something like this:
// Add foo onto the URL params
params += params ? "&" : "?";
params += "foo=1723";
If the query component started with ampersand, we could just tack on “&foo=1723” and be done with it. From a whole-URL view, there’s some sense to separating the query and the path with a distinct character like question mark, but it’s not like it would have been unparseable to say the query component starts with the first ampersand.
Next time we’ll get it right... :)
And while we’re on the subject, why has the Python library got the tools to deal with URLs as structured data spread across three different modules? Turns out it doesn’t take much to pull them all together into a Url class that can help with URL construction and parsing tasks:
import cgi, urllib, urlparse
"""A structured URL.
Create from a string or Django request, then read or write the components
through attributes `scheme`, `netloc`, `path`, `params`, `query`, and
The query is more usefully available as the dictionary `args`.
def __init__(self, url):
"""Construct from a string or Django request."""
if hasattr(url, 'get_full_path'):
url = url.get_full_path()
self.scheme, self.netloc, self.path, self.params, \
self.query, self.fragment = urlparse.urlparse(url)
self.args = dict(cgi.parse_qsl(self.query))
"""Turn back into a URL."""
self.query = urllib.urlencode(self.args)
self.scheme, self.netloc, self.path, self.params,
Now I can do stuff like:
# Redirect to one of our canonical hosts, with an extra arg.
url = Url(request)
url.netloc = THE_SECURE_HOST if request.is_secure() else THE_HOST
url.args['from'] = request.get_host()
This takes care of all the Url syntax logic for me, so I don’t have to think about question marks and ampersands ever again.