Consider parsing query string with Flask

Issue #19 resolved
Steven Maude created an issue
<drj11> SteveMaude: did you know you can go: /foo?uri=thing&uri=other_thing&uri=another_thing
<drj11> SteveMaude: and CGI web frameworks cunningly make a list
<drj11> SteveMaude: I would expect request.args.get('uri') to return a list if I've given multiple uri=. Does it not?
<drj11> SteveMaude: I'm reading: http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.MultiDict

Comments (4)

  1. Steven Maude reporter

    It seems you need to do request.args.getlist() and pass in multiple values with the same key to get a list of values.

    The problem is that some things we want as lists, others not necessarily, and we don't know the full extent of what we want to handle (as we may want new keys in the query string, so handling on a case-by-case basis isn't ideal either, e.g. if request.args['key'] == 'offset' etc).

    One way round it might be to use getlist for all query string values, but then we need to pull out single items, possibly something like:

    def parse_query_string(**kwargs):
        """ Take request.args and return a dict for passing in as **kwargs """
        args_dict = {}
        for key in kwargs:
            args = request.args.getlist(key)    
            if len(args) == 1:
                args = args[0]
            args_dict[key] = args
        return args_dict
    

    This has the advantage that the order of URIs is implicitly the order in which they appear in the query string.

    But, I tried implementing this and there's the problem that this makes URIs a single item, but the query code assumes it's a list.

    URIs can be a single item or multiple depending on the query. We could just make all single items be lists (get rid of the if in the code above) but then the query classes need to know that all these single items are actually inside lists, which seems a bit awkward (as it also affects things like output, offset, limit).

    For example, __init__ for SparqlQuery would then take a default offset of [0]. Maybe we could handle URIs as a special case and change the if to

        if len(args) == 1 and key != 'uri':
            args = args[0]
    

    For reference, the current code is: return jsonurl.parse_query(query_string)

    Let me know if you have any strong opinions either way on this @drj or anyone else!

  2. ian_hopkinson

    Having tried query string parsing on the Flask side I decided it best to do it on the query side. Basically, errors occur in constructing the query classes which can only be caught by those classes.

  3. Log in to comment