How to use restful upload multiple files with array? - python

my schema:
test_multivalues = {
'name': {'type':'string'},
'multi': {'type': 'list', 'schema': {'type': 'media'}},
'arr': {'type': 'list'},
}
I use the post data as follow:
Content-Type: multipart/form-data
name: multivalue
multi: ....file1...
multi: ....file2....
arr: [arr_value1, arr_value2]
In Eve,parameter arr will get as a list, but multi only get the first value.
I expect to get multi as a list like [file1, file2].
When I read the code, Eve use werkzeug's MultiDict.to_dict() in payload() method which only return the first value for the same key.
How can I get the key with multiple values as list ?
Updated:
Eve will raise an exception with above schema and post data:
multi:must be of list type
Updated:
Yes, I test it with curl.
curl -F "image=#text.txt" -F "image=#test.txt" http://localhost/eve/api
When I changed the code in payload() to:
v = lambda l: l if len(l) > 1 else l[0]
return dict([(k, v(request.form.getlist(k))) for k in request.form] +
[(k, v(request.files.getlist(k))) for k in request.files])
it return file list, but Eve's post method not support it, and throw an exception.

Ugly way to solve this:
def saver(filestorageobj):
app.media.put(
filestorageobj,
filename=filestorageobj.name,
content_type=filestorageobj.mimetype,
resource='test')
def pre_test_POST_callback(request):
from werkzeug.datastructures import ImmutableMultiDict
# files format: [("pics", FileStorageObject)]
pics = [saver(
upfile[1]
) for upfile in request.files.items(True) if upfile[0] == "pics"]
form = request.form.copy()
form['pics'] = pics
request.form = ImmutableMultiDict(form)
request.files = ImmutableMultiDict()

As of 0.7+ version of eve, you only need to set AUTO_COLLAPSE_MULTI_KEYS to True.

Related

How to save data from an API into a dictionary

I'm getting data from an API and saving into a list called data[].
After this, I'm sending these data to another class to format it.
I want to create a dict, so I can save these data. I'm trying to do something like this:
import json
import datetime
class MovieFormatter():
def format(self, data):
data = {
"movie_info_name": data['title']
"movie_info_duration": data['duration']
"movie_info_description": data['synopsis']
"movie_info_genres": data['genres']
"movie_info_actor": data['cast']
"movie_info_director": data['director']
data['trailers'] = data.get('trailers') or []
"dictionary": [{'url': x['url'], 'type': x['type']} for x in data['images'] + data['trailers']]
}
return data
Is this the right way to do?
It seems that the data object passed to your function is already a dictionary, from the way it has been indexed e.g. data['title'].
Try this :
_in_data = ["a","b","c"]
_out_data = ["x","y","z"]
_dict={}
print(_dict)
for i in range (len(_in_data)):
_dict[_in_data[i]]=_out_data[i]
print(_dict)

What is the most efficient way of retrieving the port value from this json list

I have the below list from which I have to retrieve the port number I want the value 50051 but what I get is port=50051 I know I can retrieve this by iterating the list and using string operations but wanted to see if there is some direct way to access this.
r = requests.get(url_service)
data = {}
data = r.json()
#Below is the json after printing
[{'ServerTag': [ 'abc-service=true',
'port=50051',
'protocol=http']
}]
print(data[0]["ServiceTags"][1]) // prints port=50051
You can do something like this perhaps:
received_dic = {
'ServerTag': [ 'abc-service=true',
'port=50051',
'protocol=http']
}
ServerTag = received_dic.get("ServerTag", None)
if ServerTag:
port = list(filter(lambda x: "port" in x, ServerTag))[0].split("=")[1]
print(port)
# 50051
Considering you have the following JSON:
[
{
"ServerTag": ["abc-service=true", "port=50051", "protocol=http"]
}
]
You can extract your value like this:
from functools import partial
# ...
def extract_value_from_tag(tags, name, default=None):
tags = map(partial(str.split, sep='='), tags)
try:
return next(value for key, value in tags if key == name)
except StopIteration:
# Tag was not found
return default
And then you just:
# Providing data is the deserialized JSON as a Python list
# Also assuming that data is not empty and ServerTag is present on the first object
tags = data[0].get('ServerTag', [])
port_number = extract_value_from_tag(tags, 'port', default='8080')

How to reference a json array element by name using Python?

In this json array:
json_string=[{"Id": "report","Value": "3001"},{"Id": "user","Value": "user123"}]
How can I get back user123 if I pass in user
When I try to do this:
content = json.loads(json_string)
content['user']
I get an error that says you have to use integer to reference an element.
I am brand new to Python.
Thanks!
content is a list so you should get the element by index first:
>>> content[1]['Value']
'user123'
>>> for d in content:
... if 'user' in d.values():
... print d['Value']
'user123'
Assuming user is always mapped to Id:
>>> for d in content:
... if d['Id'] == 'user':
... print d['Value']
One liner:
>>> [d['Value'] for d in content if d['Id'] == 'user'][0]
'user123'
Assuming you want to focus on the first occurrence of an element in the list with a given field (e.g. 'Id') with a certain value (e.g. 'user'):
def look_for(string, field, val):
return next((el['Value'] for el in string if el[field] == val))
json_string = [{"Id": "report","Value": "3001"}, {"Id": "user","Value": "user123"}]
found_val = look_for(json_string, 'Id', 'user')
produces
'user123'
Obviously, also the output field can become a parameter instead of being hardcoded to Value

Multi-valued data in DynamoDB using boto

After scouring the documentation and various tutorials, I cannot figure out how to set or update an attribute on a dynamo Item that is a multi-valued data type (number or string set). I'm using boto (boto.dynamodb2, to be specific -- not boto.dynamodb).
Trying something like this (where 'id' is the hash key):
Item(Table('test'), data={'id': '123', 'content': 'test', 'list': [1,2,3,4]}).save()
Results in this error:
TypeError: Unsupported type "<type 'list'>" for value "[1, 2, 3, 4]"
I feel like this must be possible in boto.dynamodb2, but it's odd that I can't find any examples of people doing this. (Everyone is just setting number or string attributes, not number set or string set attributes.)
Any insight on this topic and how I might get this to work with boto would be very much appreciated! I'm guessing I'm overlooking something simple. Thanks!
Okay, we were able to figure this out on our own. The problem with my example above is that I'm using a list instead of a set. The value of a multi-value attribute MUST be a set.
For example, this works:
Item(Table('test'), data={'id': '123', 'content': 'test', 'list': set([1,2,3,4])}).save()
DnyamoDB now supports Dict/List directly. Boto doesn't have support for it yet, but it's a small patch until it's supported in production.
############################################################
# Patch Dynamizer to support dict/list
############################################################
from boto.dynamodb.types import Dynamizer, get_dynamodb_type
def _get_dynamodb_type(self, attr):
if isinstance(attr, dict):
return 'M'
if isinstance(attr, list):
return 'L'
return get_dynamodb_type(attr)
def _encode_m(self, attr):
result = {}
for k, v in attr.items():
result[k] = self.encode(v)
return result
def _decode_m(self, attr):
result = {}
for k, v in attr.items():
result[k] = self.decode(v)
return result
def _encode_l(self, attr):
return [self.encode(v) for v in attr]
def _decode_l(self, attr):
return [self.decode(v) for v in attr]
Dynamizer._get_dynamodb_type = _get_dynamodb_type
Dynamizer._encode_m = _encode_m
Dynamizer._decode_m = _decode_m
Dynamizer._encode_l = _encode_l
Dynamizer._decode_l = _decode_l
############################################################
# End patch Dynamizer to support dict/list
############################################################
This works normally with boto3:
session = boto3.Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)
dynamodb = session.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('table')
list = ['1','2','3']
table.put_item(
Item={
'id': 01,
'message': list,
'timestamp': '2019-05-01 22:14:00'
}
)
Your data will be saved like the following:

How to take a dictionary and send a JSON Response

I have the following function,
def facebooktest(request):
fb_value = ast.literal_eval(request.body)
fb_foodies = Foodie.objects.filter(facebook_id__in = fb_value.values())
for fb_foodie in fb_foodies:
state = request.user.relationships.following().filter(username = fb_foodie.user.username).exists()
userData = {
'fbid': fb_foodie.facebook_id,
'followState': int(state),
}
Basically I am checking to see which of the user's facebook friends are on my django app. If they are, return the followState. The followState basically returns a 1 or a 0. 1 if the user is already following them on my Django app and 0 if they are not following their facebook friend on my Django app.
I would like to return back a json type dictionary to that user that looks like this:
[{fbid:222222222222, followState: 0}, {fbid:111111111111, followState: 1}, {fbid:435433434534, followState:1}]
EDIT
I have the dictionary structure but I just want to return it like the structure above.
def facebooktest(request):
fb_value = ast.literal_eval(request.body)
fb_foodies = Foodie.objects.filter(facebook_id__in = fb_value.values())
response = []
for fb_foodie in fb_foodies:
state = request.user.relationships.following().filter(username = fb_foodie.user.username).exists()
userData = {
'fbid': fb_foodie.facebook_id,
'followState': int(state),
}
response.append(userData)
return json.dumps(response)
There is a function in the django.forms.models package for that: model_to_dict
from django.forms.models import model_to_dict
model_to_dict(your_model, fields=[], exclude=[])
From the help:
model_to_dict(instance, fields=None, exclude=None)
Returns a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.
``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned dict.
``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned dict, even if they are listed in
the ``fields`` argument.
I think you're looking for this:
return HttpResponse(simplejson.dumps(response_dict), mimetype='application/json')
where 'response_dict' would be your dictionary.

Categories

Resources