7

im trying so submit a webpage that has checkboxes and i need up to 10 of these checkboxes checked

the problem is when i try to assign them to one name in a dict it only assigns the last one not all 10

so how can i do this here is the request code:

forms = {"_ref_ck": ref,
         "type": "create",
         "selected_items[]": sel_itms[0],
         "selected_items[]": sel_itms[1],
         "selected_items[]": sel_itms[2],
         "selected_items[]": sel_itms[3],
         "selected_items[]": sel_itms[4],
         "selected_items[]": sel_itms[5],
         "selected_items[]": sel_itms[6],
         "selected_items[]": sel_itms[7],
         "selected_items[]": sel_itms[8],
         "selected_items[]": sel_itms[9]

         }
data = urllib.urlencode(forms)
req = urllib2.Request('http://www.neopets.com/island/process_tradingpost.phtml',data)
res = self.opener.open(req)
html =  res.read()

this works but i only sends one value for "selected_itmes[]" when i look at the actual request in a web debugging proxy it sends multiple values for "selected_items[]" but i dont know how to do it with python

please help Thank you!!

Serial
  • 7,925
  • 13
  • 52
  • 71
  • possible duplicate of [Sending multiple POST data items with the same name, using AppEngine](http://stackoverflow.com/questions/3577064/sending-multiple-post-data-items-with-the-same-name-using-appengine) – andrean Aug 13 '13 at 06:12

2 Answers2

13

The problem has nothing to do with urlencode; it's that a Python dict can't hold multiple values for the same key. You can see this by printing out forms before you send it—there's only one value there for selected_items[]. That one value gets encoded just fine.

As the documentation explains, there are two ways around this.

First, you can attach a sequence of values to one key, and use the doseq=True flag:

forms = {"_ref_ck": ref,
     "type": "create",
     "selected_items[]": sel_itms[:10]
     }
 data = urllib.urlencode(forms, doseq=True)

Alternatively, you can pass a sequence of two-element tuples instead of a mapping:

forms = (("_ref_ck", ref),
         ("type", "create"),
         ("selected_items[]", sel_itms[0]),
         ("selected_items[]", sel_itms[1]),
         # ...
         )
data = urllib.urlencode(forms)

(You can also use a custom Mapping type that allows repeated keys, instead of a standard dict, but that's probably overkill. Especially since the usual way to construct such a custom Mapping type is by passing it a sequence of key-value pairs…)

abarnert
  • 354,177
  • 51
  • 601
  • 671
1

You can do this by creating a class and make it return the same string. In python3:

import urllib.parse

class Value(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name

params = {Value("selected_items[]"): "one",
Value("selected_items[]"): "two"}

data = urllib.parse.urlencode(params)
print(data)

output is:

selected_items%5B%5D=one&selected_items%5B%5D=two

Solution was taken from here

GuySoft
  • 1,723
  • 22
  • 30