Variables in strings..
Sam Penrose
see at message.body
Thu Jul 27 01:08:01 EDT 2000
In article <119330503709.20000724135021 at buz.ch>, Gabriel Ambuehl
<gabriel_ambuehl at buz.ch> wrote:
> Hello Steve,
> Monday, July 24, 2000, 12:52:30 PM, you wrote:
>
> > print "Hello %s" % names[1]
> > to the eyes of anyone but a Perl afficionado.
>
> Perhaps. But in real world (tm) CGI scripts, one needs more than just
> one variable in there. I've got Perl scripts who insert aroun 40
> variables (including array slices) during one print <<"EOF"
> instruction. I could live with the "%(myvar)" % vars() syntax if there
> would be a possibility to reference to lists and dictionary entries as
> well. Without it, it's a real pain to quickly write CGI scripts.
> Hell,
> content='<tr> <td> <a href="http://'+ pair[0] + '">' + pair[0]+ '</a>
> </td> <td>' + pair[1] + '</td><td><a href="' + PathToScript
> etc is nothing I can consider readably. (though pair1=pair[1]
> and pair2=pair[2] would do the job but that's not really what I'd
> consider elegant...)
>
>
>
>
>
>
> Best regards,
> Gabriel
>
>
>
I've been doing this for about a year now, and I have to agree that
Python string substitution syntax dominates the CGI-based systems I
write. Some observations/habits, in no particular order and with no
guarantee of non-obviousness.
1) It's all about dictionaries, as you noticed. Fortunately,
dictionaries are also generally the handiest way to move data between
HTML and databases. I tend to use tuples in situations like the example
above, when the HTML string is short and in my script; entire pages are
always read in from a file and coded for dictionaries.
2) Rather than assigning in that detail to a string or using vars(),
assign to an intermediate dictionary. Your functions start to look like:
def foo():
dict = {}
html = CONSTANT # or open('template').read()
for variable in otherDict.keys():
# add to dict according to criteria
return html % dict
3) It's helpful to create two subclasses of UserDict: one I call
PartialStringSubstitution that leaves alone any extra %(variable)s tags
rather than raising a KeyError and another, NoKeyErrors, that replaces
them with empty strings rather than raising a KeyError. I can post these
if anyone wants to see them.
4) Core control flow in my current project, a self-assembling Intranet
which bears a family relationship to Aquarium, centers around a series
of dictionaries:
i. Validate user identity, determine user action, instantiate
appropriate page object. Rest happens within object.
ii. Parse the cgi.FieldValues(), which I instantiate with
keep_blank_values=1, so as to cut through the irritating
if form.has_key('foo'):
if form['foo'].value == bar:
else:
else:
syntax. Besides checking to see if their action failed (pages with
children can't be deleted; new pages must be given names, etc.), I
convert the FieldValues to a regular dictionary, with image and data
files passed off to dedicated dictionaries and methods.
iii. If we are saving to database, assemble that dictionary now and
save, using a utility that converts dictionaries to MySQLdb.py calls.
iv. Define the template according to the action and start assembling
the main dictionary, which is a PartialStringSubstitution. Many of the
values in mainDict will themselves contain string substitution keys.
v. After creating mainDict entries for elements common to every page,
call the heart of the heart of the system, which assembles the
particular data that needs writing to HTML. There's a lot that needs to
happen here (the combination of cancellable previews and uploadable
images makes the code about three times as complicated as it would be
without them), but basically I atomize the possibilities into a series
of short methods that define dictionaries and update mainDict
appropriately. Along the way I've been building yet another dictionary
with key:value pairs that need to be inserted as hidden fields; at this
time I assemble that into an HTML string and assign the string to
mainDict['hiddenFields'].
vi. Marry the template to mainDict, then marry that to the final
NoKeyErrors dictionary, which wipes out any extra string substitution
keys and also drops their session key (no pun intended) into all of the
links on the page. Permissions are managed up in i.: when a user
requests a page, the page is drawn with the information they are
supposed to see ("You are not in this department so you can't see the
department-only calendar; you are the owner of this page so we'll
provide editing controls."); that way the user never sees a locked door.
5) The more I think about this, the more arbitrary it seems to have a
medium sized (1,200 lines now; maybe twice that on ship) system so
dominated by the need to manage string substitution syntax. OTOH,
Python's lovely object handling makes adding things like calendars
really easy. When I read Perl or Java I don't wish I was using them, but
my total coding experience consists of a year of Python, so maybe I just
don't know what I'm missing.
--
spenrose at well dot com
More information about the Python-list
mailing list