Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
a1a4b591
Commit
a1a4b591
authored
Aug 25, 2000
by
Moshe Zadka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Closing patch #101120 -- After everyone agreed.
parent
dc3d606b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 additions
and
61 deletions
+76
-61
Doc/lib/libcgi.tex
Doc/lib/libcgi.tex
+40
-35
Lib/cgi.py
Lib/cgi.py
+23
-23
Lib/test/test_cgi.py
Lib/test/test_cgi.py
+13
-3
No files found.
Doc/lib/libcgi.tex
View file @
a1a4b591
...
...
@@ -45,7 +45,7 @@ telling the client what kind of data is following. Python code to
generate a minimal header section looks like this:
\begin{verbatim}
print "Content-
t
ype: text/html" # HTML is following
print "Content-
T
ype: text/html" # HTML is following
print # blank line, end of headers
\end{verbatim}
...
...
@@ -59,9 +59,6 @@ print "<H1>This is my first CGI script</H1>"
print "Hello, world!"
\end{verbatim}
(It may not be fully legal HTML according to the letter of the
standard, but any browser will understand it.)
\subsection
{
Using the cgi module
}
\nodename
{
Using the cgi module
}
...
...
@@ -77,9 +74,16 @@ value of various environment variables set according to the CGI
standard). Since it may consume standard input, it should be
instantiated only once.
The
\class
{
FieldStorage
}
instance can be accessed as if it were a Python
dictionary. For instance, the following code (which assumes that the
\code
{
content-type
}
header and blank line have already been printed)
The
\class
{
FieldStorage
}
instance can be indexed like a Python
dictionary, and also supports the standard dictionary methods
\function
{
has
_
key()
}
and
\function
{
keys()
}
.
Form fields containing empty strings are ignored
and do not appear in the dictionary; to keep such values, provide
the optional
\samp
{
keep
_
blank
_
values
}
argument when creating the
\class
{
FieldStorage
}
instance.
For instance, the following code (which assumes that the
\code
{
Content-Type
}
header and blank line have already been printed)
checks that the fields
\code
{
name
}
and
\code
{
addr
}
are both set to a
non-empty string:
...
...
@@ -87,23 +91,30 @@ non-empty string:
form = cgi.FieldStorage()
form
_
ok = 0
if form.has
_
key("name") and form.has
_
key("addr"):
if form["name"].value != "" and form["addr"].value != "":
form
_
ok = 1
form
_
ok = 1
if not form
_
ok:
print "<H1>Error</H1>"
print "Please fill in the name and addr fields."
return
print "<p>name:", form["name"].value
print "<p>addr:", form["addr"].value
...further form processing here...
\end{verbatim}
Here the fields, accessed through
\samp
{
form[
\var
{
key
}
]
}
, are
themselves instances of
\class
{
FieldStorage
}
(or
\class
{
MiniFieldStorage
}
, depending on the form encoding).
The
\member
{
value
}
attribute of the instance yields the string value
of the field. The
\function
{
getvalue()
}
method returns this string value
directly; it also accepts an optional second argument as a default to
return if the requested key is not present.
If the submitted form data contains more than one field with the same
name, the object retrieved by
\samp
{
form[
\var
{
key
}
]
}
is not a
\class
{
FieldStorage
}
or
\class
{
MiniFieldStorage
}
instance but a list of such instances. If you expect this possibility
instance but a list of such instances. Similarly, in this situation,
\samp
{
form.getvalue(
\var
{
key
}
)
}
would return a list of strings.
If you expect this possibility
(i.e., when your HTML form contains multiple fields with the same
name), use the
\function
{
type()
}
function to determine whether you
have a single instance or a list of instances. For example, here's
...
...
@@ -111,27 +122,21 @@ code that concatenates any number of username fields, separated by
commas:
\begin{verbatim}
username = form["username"]
if type(
usernam
e) is type([]):
value = form.getvalue("username", "")
if type(
valu
e) is type([]):
# Multiple username fields specified
usernames = ""
for item in username:
if usernames:
# Next item -- insert comma
usernames = usernames + "," + item.value
else:
# First item -- don't insert comma
usernames = item.value
usernames = ",".join(value)
else:
# Single username field specified
usernames =
username.
value
# Single
or no
username field specified
usernames = value
\end{verbatim}
If a field represents an uploaded file, the value attribute reads the
If a field represents an uploaded file, accessing the value via the
\member
{
value
}
attribute or the
\function
{
getvalue()
}
method reads the
entire file in memory as a string. This may not be what you want.
You can test for an uploaded file by testing either the
filename
attribute or the
file
attribute. You can then read the data at
leisure from the
file
attribute:
You can test for an uploaded file by testing either the
\member
{
filename
}
attribute or the
\member
{
file
}
attribute. You can then read the data at
leisure from the
\member
{
file
}
attribute:
\begin{verbatim}
fileitem = form["userfile"]
...
...
@@ -157,7 +162,8 @@ When a form is submitted in the ``old'' format (as the query string or
as a single data part of type
\mimetype
{
application/x-www-form-urlencoded
}
), the items will actually
be instances of the class
\class
{
MiniFieldStorage
}
. In this case, the
list, file and filename attributes are always
\code
{
None
}
.
\member
{
list
}
,
\member
{
file
}
, and
\member
{
filename
}
attributes are
always
\code
{
None
}
.
\subsection
{
Old classes
}
...
...
@@ -233,23 +239,22 @@ exception.
\begin{funcdesc}
{
parse
_
multipart
}{
fp, pdict
}
Parse input of type
\mimetype
{
multipart/form-data
}
(for
file uploads). Arguments are
\var
{
fp
}
for the input file and
\var
{
pdict
}
for
the dictionary containing other parameters of
\code
{
content-type
}
header
\var
{
pdict
}
for
a dictionary containing other parameters in
the
\code
{
Content-Type
}
header.
Returns a dictionary just like
\function
{
parse
_
qs()
}
keys are the
field names, each value is a list of values for that field. This is
easy to use but not much good if you are expecting megabytes to be
uploaded --- in that case, use the
\class
{
FieldStorage
}
class instead
which is much more flexible. Note that
\code
{
content-type
}
is the
raw, unparsed contents of the
\code
{
content-type
}
header.
which is much more flexible.
Note that this does not parse nested multipart parts --- use
\class
{
FieldStorage
}
for that.
\end{funcdesc}
\begin{funcdesc}
{
parse
_
header
}{
string
}
Parse a
header like
\code
{
content-type
}
into a main
content-typ
e and a dictionary of parameters.
Parse a
MIME header (such as
\code
{
Content-Type
}
)
into a main
valu
e and a dictionary of parameters.
\end{funcdesc}
\begin{funcdesc}
{
test
}{}
...
...
@@ -432,7 +437,7 @@ For example:
\begin{verbatim}
import sys
import traceback
print "Content-
t
ype: text/html"
print "Content-
T
ype: text/html"
print
sys.stderr = sys.stdout
try:
...
...
@@ -454,7 +459,7 @@ built-in modules):
\begin{verbatim}
import sys
sys.stderr = sys.stdout
print "Content-
t
ype: text/plain"
print "Content-
T
ype: text/plain"
print
...your code here...
\end{verbatim}
...
...
Lib/cgi.py
View file @
a1a4b591
...
...
@@ -19,7 +19,7 @@ written in Python.
# responsible for its maintenance.
#
__version__
=
"2.
2
"
__version__
=
"2.
3
"
# Imports
...
...
@@ -31,6 +31,7 @@ import os
import
urllib
import
mimetools
import
rfc822
import
UserDict
from
StringIO
import
StringIO
...
...
@@ -166,11 +167,10 @@ def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
"""
dict
=
{}
for
name
,
value
in
parse_qsl
(
qs
,
keep_blank_values
,
strict_parsing
):
if
len
(
value
)
or
keep_blank_values
:
if
dict
.
has_key
(
name
):
dict
[
name
].
append
(
value
)
else
:
dict
[
name
]
=
[
value
]
if
dict
.
has_key
(
name
):
dict
[
name
].
append
(
value
)
else
:
dict
[
name
]
=
[
value
]
return
dict
def
parse_qsl
(
qs
,
keep_blank_values
=
0
,
strict_parsing
=
0
):
...
...
@@ -201,9 +201,10 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
if
strict_parsing
:
raise
ValueError
,
"bad query field: %s"
%
`name_value`
continue
name
=
urllib
.
unquote
(
string
.
replace
(
nv
[
0
],
'+'
,
' '
))
value
=
urllib
.
unquote
(
string
.
replace
(
nv
[
1
],
'+'
,
' '
))
r
.
append
((
name
,
value
))
if
len
(
nv
[
1
])
or
keep_blank_values
:
name
=
urllib
.
unquote
(
string
.
replace
(
nv
[
0
],
'+'
,
' '
))
value
=
urllib
.
unquote
(
string
.
replace
(
nv
[
1
],
'+'
,
' '
))
r
.
append
((
name
,
value
))
return
r
...
...
@@ -537,6 +538,17 @@ class FieldStorage:
else
:
return
found
def
getvalue
(
self
,
key
,
default
=
None
):
"""Dictionary style get() method, including 'value' lookup."""
if
self
.
has_key
(
key
):
value
=
self
[
key
]
if
type
(
value
)
is
type
([]):
return
map
(
lambda
v
:
v
.
value
,
value
)
else
:
return
value
.
value
else
:
return
default
def
keys
(
self
):
"""Dictionary style keys() method."""
if
self
.
list
is
None
:
...
...
@@ -706,7 +718,7 @@ class FieldStorage:
# Backwards Compatibility Classes
# ===============================
class
FormContentDict
:
class
FormContentDict
(
UserDict
.
UserDict
)
:
"""Basic (multiple values per field) form content as dictionary.
form = FormContentDict()
...
...
@@ -720,20 +732,8 @@ class FormContentDict:
"""
def
__init__
(
self
,
environ
=
os
.
environ
):
self
.
dict
=
parse
(
environ
=
environ
)
self
.
dict
=
self
.
data
=
parse
(
environ
=
environ
)
self
.
query_string
=
environ
[
'QUERY_STRING'
]
def
__getitem__
(
self
,
key
):
return
self
.
dict
[
key
]
def
keys
(
self
):
return
self
.
dict
.
keys
()
def
has_key
(
self
,
key
):
return
self
.
dict
.
has_key
(
key
)
def
values
(
self
):
return
self
.
dict
.
values
()
def
items
(
self
):
return
self
.
dict
.
items
()
def
__len__
(
self
):
return
len
(
self
.
dict
)
class
SvFormContentDict
(
FormContentDict
):
...
...
Lib/test/test_cgi.py
View file @
a1a4b591
...
...
@@ -116,19 +116,27 @@ def main():
d
=
do_test
(
orig
,
"POST"
)
assert
d
==
expect
,
"Error parsing %s"
%
repr
(
orig
)
d
=
{
'QUERY_STRING'
:
orig
}
fcd
=
cgi
.
FormContentDict
(
d
)
sd
=
cgi
.
SvFormContentDict
(
d
)
env
=
{
'QUERY_STRING'
:
orig
}
fcd
=
cgi
.
FormContentDict
(
env
)
sd
=
cgi
.
SvFormContentDict
(
env
)
fs
=
cgi
.
FieldStorage
(
environ
=
env
)
if
type
(
expect
)
==
type
({}):
# test dict interface
assert
len
(
expect
)
==
len
(
fcd
)
assert
norm
(
expect
.
keys
())
==
norm
(
fcd
.
keys
())
assert
norm
(
expect
.
values
())
==
norm
(
fcd
.
values
())
assert
norm
(
expect
.
items
())
==
norm
(
fcd
.
items
())
assert
fcd
.
get
(
"nonexistent field"
,
"default"
)
==
"default"
assert
len
(
sd
)
==
len
(
fs
)
assert
norm
(
sd
.
keys
())
==
norm
(
fs
.
keys
())
assert
fs
.
getvalue
(
"nonexistent field"
,
"default"
)
==
"default"
# test individual fields
for
key
in
expect
.
keys
():
expect_val
=
expect
[
key
]
assert
fcd
.
has_key
(
key
)
assert
norm
(
fcd
[
key
])
==
norm
(
expect
[
key
])
assert
fcd
.
get
(
key
,
"default"
)
==
fcd
[
key
]
assert
fs
.
has_key
(
key
)
if
len
(
expect_val
)
>
1
:
single_value
=
0
else
:
...
...
@@ -137,9 +145,11 @@ def main():
val
=
sd
[
key
]
except
IndexError
:
assert
not
single_value
assert
fs
.
getvalue
(
key
)
==
expect_val
else
:
assert
single_value
assert
val
==
expect_val
[
0
]
assert
fs
.
getvalue
(
key
)
==
expect_val
[
0
]
assert
norm
(
sd
.
getlist
(
key
))
==
norm
(
expect_val
)
if
single_value
:
assert
norm
(
sd
.
values
())
==
\
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment