How to create URL Parameters from a list - python

I have a form with multiple select field. It is working through GET method.
An example of request parameters generated by the form:
action=not-strummed&action=not-rewarded&keywords=test&page=2
Note that there is two "action" parameters. This is happening because of the multiple select.
What I want to do is:
Make a dict from parameters
Remove "page" key from the dict
Transform-back the dict into the parameter string
The urllib.urlencode() isn't smart enough to generate url parameters from the list.
For example:
{
"action": [u"not-strummed", u"not-rewarded"]
}
urllib.urlencode() transforms this dict as:
action=%5Bu%27not-strummed%27%2C+u%27not-rewarded%27%5D
This is completely wrong and useless.
That's why i wrote this iteration code to re-generate url parameters.
parameters_dict = dict(self.request.GET.iterlists())
parameters_dict.pop("page", None)
pagination_parameters = ""
for key, value_list in parameters_dict.iteritems():
for value in value_list:
pagination_item = "&%(key)s=%(value)s" % ({
"key": key,
"value": value,
})
pagination_parameters += pagination_item
It is working well. But it doesn't cover all possibilities and it is definitely not very pythonic.
Do you have a better (more pythonic) idea for creating url parameters from a list?
Thank you

You should be able to use the second doseq parameter urlencode offers:
http://docs.python.org/2/library/urllib.html
So basically, you can pass a dictionary of lists to urlencode like so:
urllib.urlencode(params, True)
And it will do the right thing.

Related

How to find a value of a key in a nested dictionary with lists?

There's some very strange json payloads that I need to parse and I'm complete stuck..
Say I have a nested dictionary with lists that looks like this:
test_dict1 = {
"blah":"blah",
"alerts": [{"test1":"1", "test":"2"}],
"foo": {
"foo":"bar",
"foo1": [{"test3":"3"}]
}}
Is there a function that would be able to give me the value of the key test3? Or rather the first value for the first occurrence of the key test3
Edit
What I meant was a function where I can search for the key test3, since I am mainly concerned about the key and the different dictionaries that I could get may have different structures
Since you do not know how deep inside the value is, it is prob advisable to use a recursive function to iterate through all the layers till it's found. I used DFS below.
def search(ld, find):
if(type(ld)==list):
for i in ld:
if(type(i)==list or type(i)==dict):
result=search(i, find)
if(result!=None): return result
elif(type(ld)==dict):
try:
return ld[find]
except(KeyError):
for i in ld:
if(type(ld[i])==list or type(ld[i])):
result=search(ld[i], find)
if(result!=None): return result
else:
return None
test_dict1 = {
"blah":"blah",
"alerts": [{"test1":"1", "test":"2"}],
"foo": {
"foo":"bar",
"foo1": [{"test3":"3"}]
}}
print(search(test_dict1, "test3"))
Just access it like you would any other nested structure:
test_dict1["foo"]["foo1"][0]["test3"]
Also, what do you mean by the first occurrence? Dictionaries don't have a specific order, so that won't really do much for you.
If you only want the value of test3 then this is how you can get it,
test_dict1["foo"]["foo1"][0]["test3"]
But if you want value dynamically then it will be done with a different approch.
See, you can use a key name when you are working with dictionaries and indexing when it comes to the list.

I can't get a value from a JSON API response in python

So I am struggling with getting a value from a JSON response. Looking in other post I have managed to write this code but when I try to search for the key (character_id) that I want in the dictionary python says that the key doesn't exist. My solution consists in getting the JSON object from the response, converting it into a string with json.dumps() and the converting it into a dictionary with json.loads(). Then I try to get 'character_id' from the dictionary but it doesn't exist. I am guessing it is related with the format of the dictionary but I have little to none experience in python. The code that makes the query and tries to get the values is this: (dataRequest is a fuction that makes the request and return the response from the api)
characterName = sys.argv[1];
response = dataRequest('http://census.daybreakgames.com/s:888/get/ps2:v2/character/?name.first_lower=' + characterName + '&c:show=character_id')
jsonString = json.dumps(response.json())
print(jsonString)
dic = json.loads(jsonString)
print(dic)
if 'character_id' in dic:
print(dic['character_id'])
The output of the code is:
{"character_list": [{"character_id": "5428662532301799649"}], "returned": 1}
{'character_list': [{'character_id': '5428662532301799649'}], 'returned': 1}
Welcome #Prieto! From what I can see, you probably don't need to serialize/de-serialize the JSON -- response.json() returns a python dictionary object already.
The issue is that you are looking for the 'character_id' key at the top-level of the dictionary, when it seems to be embedded inside another dictionary, that is inside a list. Try something like this:
#...omitted code
for char_obj in dic["character_list"]:
if "character_id" in char_obj:
print(char_obj["character_id"])
if your dic is like {"character_list": [{"character_id": "5428662532301799649"}], "returned": 1}
you get the value of character_id by
print(dic['character_list'][0][character_id])
The problem here is that you're trying to access a dictionary where the key is actually character_list.
What you need to do is to access the character_list value and iterate over or filter the character_id you want.
Like this:
print(jsonString)
dic = json.loads(jsonString)
print(dic)
character_information = dic['character_list'][0] # we access the character list and assume it is the first value
print(character_information["character_id"]) # this is your character id
The way I see it, the only hiccup with the code is this :
if 'character_id' in dic:
print(dic['character_id'])
The problem is that, the JSON file actually consists of actually 2 dictionaries , first is the main one, which has two keys, character_list and returned. There is a second sub-dictionary inside the array, which is the value for the key character_list.
So, what your code should actually look like is something like this:
for i in dic["character_list"]:
print(i["character_id"])
On a side-note, it will help to look at JSON file in this way :
{
"character_list": [
{
"character_id": "5428662532301799649"
}
],
"returned": 1
}
,where, elements enclosed in curly-brackets'{}' imply they are in a dictionary, whereas elements enclosed in curly-brackets'[]' imply they are in a list

Accessing Nested JSON [AWS Metadata] with Python

I'm using Lambda to run through my AWS account, returning a list of all instances. I need to be able to print out all of the 'VolumeId' values, but I can't work out how to access them as they are nested. I am able to print out the first VolumeId for each instance, however, some of the instances have several volumes, and some only have one. I think I know why I get these results, but I can't work out what to do to get all of them back.
Here's a snippet of what the JSON for one instance looks like:
{
'Groups':[],
'Instances':[
{
'AmiLaunchIndex':0,
'ImageId':'ami-0',
'InstanceId':'i-0123',
'InstanceType':'big',
'KeyName':'nonprod',
'LaunchTime':'date',
'Monitoring':{
'State':'disabled'
},
'Placement':{
'AvailabilityZone':'world',
'GroupName':'',
'Tenancy':'default'
},
'PrivateDnsName':'secret',
'PrivateIpAddress':'1.2.3.4',
'ProductCodes':[
],
'PublicDnsName':'',
'State':{
'Code':80,
'Name':'stopped'
},
'StateTransitionReason':'User initiated',
'SubnetId':'subnet-1',
'VpcId':'vpc-1',
'Architecture':'yes',
'BlockDeviceMappings':[
{
'DeviceName':'/sda',
'Ebs':{
'AttachTime':'date',
'DeleteOnTermination':True,
'Status':'attached',
'VolumeId':'vol-1'
}
},
{
'DeviceName':'/sdb',
'Ebs':{
'AttachTime':'date'),
'DeleteOnTermination':False,
'Status':'attached',
'VolumeId':'vol-2'
}
}
],
This is what I'm doing to get the first VolumeId:
ec2client = boto3.client('ec2')
ec2 = ec2client.describe_instances()
for reservation in ec2["Reservations"]:
for instance in reservation["Instances"]:
instanceid = instance["InstanceId"]
volumes = instance["BlockDeviceMappings"][0]["Ebs"]["VolumeId"]
print("The associated volume IDs for this instance are: ",(volumes))
I think the reason that I'm getting just the first ID is because I'm referencing the first element within "BlockDeviceMappings", but I can't work out how to get the other ones. If I try it without specifying the [0], I get the list indices must be integers or slices, not str error. I tried to use a dictionary instead of a list too, but felt like I was barking up the wrong tree with that one. Any suggestions/help would be appreciated!
One possible answer, not particularly pythonic
...
id_list = []
volumes_data = instance["BlockDeviceMappings"]
for element in volumes_data:
id_list.append(element["Ebs"]["VolumeId"])
Or else use json.loads and then iterate though json using .get syntax like the final answer in this

Using a dict to call functions from a string

I would like the first two words of a user input string to be read as function arguments for where to save the string. I've settled on using a dict instead of many if statements, but I'm not sure how to structure the dict.
I believe this is a correct start:
input: "question physics What happens to atoms when they are hit by photons?"
result: program saves the input in location questions\physics
raw_entry = input("Enter text in the following format: type subtype text")
instructions = raw_entry.split()[:2]
The two words (each being a "get_id" in the example) will designate where to save the text. This example seems to be what I'm looking for, but I'm not sure how to change it for my case.
function_dict = {'get_id':
(
# function
requests.get,
# tuple of arguments
(url + "/users/" + user,),
# dict of keyword args
{'headers': self.headers}
)
}
Let me know if I'm going about this logically or if it doesn't make sense. Thanks!
You will need to define the functions separately from the dictionary
For example:
def get_id():
... the function's code ...
function_dict = { "get_id":get_id, ... }
you can then call the function with its keyword:
function_dict["get_id"]()
but you can also do this without a dictionary if the keyword is the same as the function name:
globals()["get_id"]()

Modifying a python dictionary from user inputted dot notation

I'm trying to provide an API like interface in my Django python application that allows someone to input an id and then also include key/values with the request as form data.
For example the following field name and values for ticket 111:
ticket.subject = Hello World
ticket.group_id = 12345678
ticket.collaborators = [123, 4567, 890]
ticket.custom_fields: [{id: 32656147,value: "something"}]
On the backend, I have a corresponding Dict that should match this structure (and i'd do validation). Something like this:
ticket: {
subject: "some subject I want to change",
group_id: 99999,
collaborator_ids: [ ],
custom_fields: [
{
id: 32656147,
value: null
}
]
}
1) I'm not sure exactly the best way to parse the dot notation there, and
2) Assuming I am able to parse it, how would I be able to change the values of the Dict to match what was passed in. I'd imagine maybe something like a class with these inputs?
class SetDictValueFromUserInput(userDotNotation, userNewValue, originalDict)
...
SetDictValueFromUserInput("ticket.subject", "hello world", myDict)
Fastest way is probably splitting the string and indexing based on seperation. For example:
obj = "ticket.subject".split(".")
actual_obj = eval(obj[0]) # this is risky, they is a way around this if you just use if statements and predifined variables.
actual_obj[obj[1]] = value
To have further indexing where an object like ticket.subject.name might work try using a for loop as so.
for key in obj[1:-2]: # basically for all the values in between the object name and the defining key
actual_obj = actual_obj[key] # make the new object based on the value in-between.
actual_obj[obj[-1]] = value

Categories