[Tutor] FieldStorage solution summary

Lance E Sloan lsloan@umich.edu
Tue, 01 May 2001 09:09:01 -0400


I want to say thanks to Daniel Yoo and others (sorry, I seem to have
misplaced some of the messages I received) for answering my questions
about converting a FieldStorage object into a dictionary.  I think the
best way I could thank them and help others is to contribute the
solution to my problem back to the list.

The problem was that I'm using FieldStorage objects from the cgi module
and the DocumentTemplate module (pried out of Zope) to write some
CGIs.  The DocumentTemplate functions can use a dictionary to fill in
blanks in the templates by name.  In many cases, I wanted the CGIs to
print what the user had just submitted, which is in a FieldStorage
object and that's not quite like a dictionary.  Sometimes I might also
have one or more other dictionaries with values that I want printed
along with the values from FieldStorage.

With the suggestions I had gotten about converting FieldStorage to a
dictionary, I came up with this function, dictcat, that will take any
number of dictionaries or FieldStorage objects and concatenate them
into a single dictionary.  When you run this as-is, it will print out
the results of the examples:

    import cgi

    def dictcat(*dicts):
        """
    Concatenate any number of dictionary or FieldStorage objects
    together, ignoring non-dictionaries.  If the objects have
    conflicting keys, the last one wins.  If a FieldStorage object
    has multiple values for a key, they are stored in the resulting
    dictionary as a list.
        """

        if len(dicts) == 0:
            return(None)
        all = {}
        for d in dicts:
            if (isinstance(d, cgi.FieldStorage)):
                for k in d.keys():
                    # use getvalue here in case multiple fields with same name
                    all[k] = d.getvalue(k)
            if (type(d) == type({})):
                all.update(d)
        if (all == {}):
            return(None)
        else:
            return(all)

    # Examples...
    if (__name__ == '__main__'):
        import os

        x = {'a': 'xa', 'b': 'xb'}
        y = {'a': 'ya', 'c': 'yc', 'd': 'yd'}

        print x
        print y

        # order matters when there are duplicate keys
        # the last one wins
        print dictcat(x, y)
        print dictcat(y, x)

        # more than two are allowed
        print dictcat(vars(), x, y)

        # non-dictionaries are ignored
        print dictcat(x, 5)
        print dictcat(y, dir())
        print dictcat('lsloan', 10)

        # an empty argument list is handled gracefully, too
        print dictcat()

        # simulate some CGI input
        os.environ['QUERY_STRING'] = 'years=5&name=George&name=Jerry'
        f = cgi.FieldStorage()
        print f
        print dictcat(f, x)

Hope this helps other Python newbies.  I would also appreciate
critiques/suggestions from Python experts if they think I should be
doing this differently or if they know a better way.

--
Lance E Sloan
Web Services, Univ. of Michigan: Full-service Web and database design,
development, and hosting.  Specializing in Perl & Python CGIs.
http://websvcs.itd.umich.edu/ - "Putting U on the Web"