I am working in Angular and I am using Http Request and Response.
Is it possible to send multiple arguments in 'Response'.
Angular file:
this.http.get("api/agent/applicationaware").subscribe((data:any)...
python file:
def get(request):
...
return Response(serializer.data)
I want to send multiple arguments in the Response.
Like
return Response(serializer.data,obj.someothervalue)
can you help me with this?
Thanks in advance :)
You can return a dictionary
return Response({'serializer_data': serializer.data, 'some_other_value': obj.someothervalue})
Or you can append someothervalue to serializer.data
data = serializer.data
data['someothervalue'] = obj.someothervalue
return Response(data)
If obj.someothervalue is a dictionary as well, then you can merge two dictionaries:
data = serializer.data.copy()
data.update(obj.someothervalue)
return Response(data)
add a dictionary
dict = {}
dict['details'] = serializer.data
dict['other'] = someotherdata
return Response(dict)
hope this helps
You need to decide a protocol for API response first and then you can plan accordingly.
To answer your question, YES you can send multiple args in response.
You can create a dictionary/list and put all the values you want to send inside it. Now send that dictionary/list as your response.
I would recommend something kind of this :
response = dict()
response["data"] = dict()
response["data"]["serializer_data"] = serializer.data
response["data"]["some_other_value"] = obj.someothervalue
return Response(response)
On the receiving end of the response you will have to read the response data in similar way you sent it.
Related
I have a device that do some calculations and then i want to send it with help of request to my site:
import requests
params = {'data1': '47237582'}
r =requests.get("http://127.0.0.1:8000/", data = params)
print(r)
I have a django site. How can i save the value of my request for later display?
def read(request):
if request.method == 'GET':
msg = request.GET['data1']
And how can i save it to database?
First, create a model called Message, fields maybe: msg and from, it actually depends on how you want to store the msg,
Then after getting the msg with msg = request.GET['data1'] store the msg with msg_obj = Message.objects.create(msg=msg, ...other-fields if any)
If you are gonna have different keys (i.e columns) for each request, then I say you use MongoDB, which will allow you save different set of key-values in a single document.
I just made an ajax request to a DJango View, it give me back the data, but i don't know how to get only the fields that i want.
This is the part of my view:
if request.method == 'POST':
txt_codigo_producto = request.POST.get('codigobarras_producto')
response_data = {}
resp_producto=Producto.objects.all().filter(codigobarras_producto=txt_codigo_producto)
resp_inventario=InventarioProducto.objects.all().filter(producto_codigo_producto__in=resp_producto).order_by('-idinventario_producto')[:1]
resp_precio=Precio.objects.all().filter(producto_codigo_producto__in=resp_producto,estado_precio=1).order_by('-idprecio')[:1] #
response_data['codprod']=serializers.serialize('json', list(resp_producto), fields=('codigo_producto'))
response_data['inventario']=serializers.serialize('json', list(resp_inventario), fields=('idinventario_producto'))
response_data['nombre']=serializers.serialize('json', list(resp_producto), fields=('nombre_producto'))
response_data['valorprod']=serializers.serialize('json', list(resp_precio), fields=('valor_precio'))
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
"json" is the name of the array that I get as response from the view, I send it to the console, as this:
console.log(JSON.stringify(json));
And i get this:
{"codprod":"[{\"model\": \"myapp.producto\", \"fields\": {}, \"pk\": 1}]",
"nombre":"[{\"model\": \"myapp.producto\", \"fields\": {\"nombre_producto\": \"Pantal\\u00f3n de lona \"}, \"pk\": 1}]",
"valorprod":"[{\"model\": \"myapp.precio\", \"fields\": {\"valor_precio\": \"250.00\"}, \"pk\": 1}]",
"inventario":"[{\"model\": \"myapp.inventarioproducto\", \"fields\": {}, \"pk\": 1}]"}
I tried this:
console.log(JSON.stringify(json.codprod));
With that I get this:
"[{\"model\": \"myapp.producto\", \"fields\": {}, \"pk\": 1}]"
But if I try something like json.codprod.pk or json.codprod[0] or json.codprod["pk] I get undefined in the console.
I want to know how to acces to those fields, in "valorprod" I want the "valor_precio" value, so it must be "250.00", in "nombre" I want the value of "nombre_producto" it must be "Pantal\u00f3n de lona".
Hope you can give me a hint. I think this is a JSON syntax problem, but I'm new with this.
Following Piyush S. Wanare and Roshan instructions, I have made some changes on the view:
resp_producto=Producto.objects.filter(codigobarras_producto=txt_codigo_producto)
resp_inventario=InventarioProducto.objects.filter(producto_codigo_producto__in=resp_producto).order_by('-idinventario_producto')[:1].only('idinventario_producto')
resp_precio=Precio.objects.filter(producto_codigo_producto__in=resp_producto,estado_precio=1).order_by('-idprecio')[:1].only('valor_precio')
resp_productonombre=Producto.objects.filter(codigobarras_producto=txt_codigo_producto).only('nombre_producto')
resp_productocodigo=Producto.objects.filter(codigobarras_producto=txt_codigo_producto).only('codigo_producto')
response_data = {'codprod': resp_productocodigo,'inventario':resp_inventario,'nombre':resp_productonombre,'valorprod':resp_precio}
return HttpResponse(
json.dumps(list(response_data)),
content_type="application/json"
)
But I get empty fields in the console:
["nombre","valorprod","codprod","inventario"]
Another edit, and the code that worked:
I used the views as they was at the beginning, with the double encoding, I just deleted the "codprod" part, but I wrote this on the ajax response code:
var res_valorprod=JSON.parse(json.valorprod);
var res_inventario=JSON.parse(json.inventario);
var res_nombre=JSON.parse(json.nombre);
var campos_valorprod =res_valorprod[0].fields;
var campos_nombre =res_nombre[0].fields;
console.log(res_nombre[0].pk);
console.log(campos_valorprod.valor_precio);
console.log(res_inventario[0].pk);
console.log(campos_nombre.nombre_producto);
This is working, I get what I want, but if you know something better to acces to the multiple nested JSON fields, I will be glad to know it. User dsgdfg gave me a hint.
You are doing multiple encoding, i.e. first you using serializers.serialize and then json.dumps.
Use only json.dumps and content_type as json like this, without using serializers.
response_dict = {'your_data_key': 'and your values'}
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
and then in client side you are not required to do JSON.stringify(json.codprod) .
As you sent content_type='application/json', it parse response as json.
console.log(resp.your_data_key); #will print proper response yor data values.
Answer to your first question:-
You can change your queries as follows:
resp_producto=Producto.objects.filter(codigobarras_producto=txt_codigo_producto).only('requiredField')
resp_inventario=InventarioProducto.objects.filter(producto_codigo_producto__in=resp_producto).only('requiredField').order_by('-idinventario_producto')[:1]
resp_precio=Precio.objects.filter(producto_codigo_producto__in=resp_producto,estado_precio=1).only('requiredField').order_by('-idprecio')[:1]
Then serialize it.
response_data['codprod']=serializers.serialize('json', list(resp_producto), fields=('codigo_producto'))
response_data['inventario']=serializers.serialize('json', list(resp_inventario), fields=('idinventario_producto'))
response_data['nombre']=serializers.serialize('json', list(resp_producto), fields=('nombre_producto'))
response_data['valorprod']=serializers.serialize('json', list(resp_precio), fields=('valor_precio'))
Suggestion:- It will be better if you create single {} by iterating through each required objects and create list [{},{}] rather than serializing it, and dump it as you have done like,
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
Then at FrontEnd you should use JSON.parse(responceData) for indexing over it.
This question already has answers here:
HTTP requests and JSON parsing in Python [duplicate]
(8 answers)
Closed 7 years ago.
I am creating a Django web app.
There is a function which creates a JSON response like this:
def rest_get(request, token):
details = Links.get_url(Links, token)
result={}
if len(details)>0:
result['status'] = 200
result['status_message'] = "OK"
result['url'] = details[0].url
else:
result['status'] = 404
result['status_message'] = "Not Found"
result['url'] = None
return JsonResponse(result)
And I get the response in the web browser like this:
{"status": 200, "url": "http://www.bing.com", "status_message": "OK"}
Now from another function I want to consume that response and extract the data out of it. How do I do it?
You can use the json library in python to do your job. for example :
json_string = '{"first_name": "tom", "last_name":"harry"}'
import json
parsed_json = json.loads(json_string)
print(parsed_json['first_name'])
"tom"
Since you have created a web app. I am assuming you have exposed a URL from which you can get you JSON response, for example http://jsonplaceholder.typicode.com/posts/1.
import urllib2
import json
data = urllib2.urlopen("http://jsonplaceholder.typicode.com/posts/1").read()
parsed_json = json.loads(data)
The urlopen function sends a HTTP GET request at the given URL. parsed_json is a variable of the type map and you can extract the required data from it.
print parsed_json['userId']
1
The answer I want to suggest is a little different. In your scenario - where one function needs to be accessed from both server and client end, I would suggest provide some extra parameter and change the output based on that. This reduces overheads and unnecessary conversions.
For example, if you pass in an extra parameter and change the result like this, you don't need JSON parsing on python. Of course there are solutions to do that, but why need converting to json and then parsing back when you can avoid that totally?
def rest_get(request, token, return_json=True):
details = Links.get_url(Links, token)
result={}
if len(details)>0:
result['status'] = 200
result['status_message'] = "OK"
result['url'] = details[0].url
else:
result['status'] = 404
result['status_message'] = "Not Found"
result['url'] = None
if return_json: # this is web response, so by default return_json = True
return JsonResponse(result)
return result
Then in your python code call like this -
rest_get(request, token, return_json=False): # we are passing False, so the return type is dictionary and we can use it right away.
I was trying to modify the code example here but it seems that jsonify is making it hard... I did the following without jsonify:
#app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
response = error.to_dict()
response.status_code = error.status_code
return response
Originally, the third line was like:
response = jsonify(error.to_dict())
How can I make this work? I don't want to use JSON. Only text/html
Well, I presume that error.to_dict() returns a dict, which wouldn't have a status code attribute (it's just a regular old dict). You might try this instead:
#app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
response = error.to_dict()
response["status_code"] = error.status_code
return response
That said, it seems odd that the dictionary wouldn't already have the error code in it. Maybe a bit more detail on what what you are trying to accomplish would help? If you don't call the second-to-last line, and just return response, what do you see?
In order to test a Flask application, I got a flask test client POSTing request with files as attachment
def make_tst_client_service_call1(service_path, method, **kwargs):
_content_type = kwargs.get('content-type','multipart/form-data')
with app.test_client() as client:
return client.open(service_path, method=method,
content_type=_content_type, buffered=True,
follow_redirects=True,**kwargs)
def _publish_a_model(model_name, pom_env):
service_url = u'/publish/'
scc.data['modelname'] = model_name
scc.data['username'] = "BDD Script"
scc.data['instance'] = "BDD Stub Simulation"
scc.data['timestamp'] = datetime.now().strftime('%d-%m-%YT%H:%M')
scc.data['file'] = (open(file_path, 'rb'),file_name)
scc.response = make_tst_client_service_call1(service_url, method, data=scc.data)
Flask Server end point code which handles the above POST request is something like this
#app.route("/publish/", methods=['GET', 'POST'])
def publish():
if request.method == 'POST':
LOG.debug("Publish POST Service is called...")
upload_files = request.files.getlist("file[]")
print "Files :\n",request.files
print "Upload Files:\n",upload_files
return render_response_template()
I get this Output
Files:
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>)])
Upload Files:
[]
If I change
scc.data['file'] = (open(file_path, 'rb'),file_name)
into (thinking that it would handle multiple files)
scc.data['file'] = [(open(file_path, 'rb'),file_name),(open(file_path, 'rb'),file_name1)]
I still get similar Output:
Files:
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>), ('file', <FileStorage: u'Second_XML.xml' ('application/xml')>)])
Upload Files:
[]
Question:
Why request.files.getlist("file[]") is returning an empty list?
How can I post multiple files using flask test client, so that it can be retrieved using request.files.getlist("file[]") at flask server side ?
Note:
I would like to have flask client I dont want curl or any other client based solutions.
I dont want to post single file in multiple requests
Thanks
Referred these links already:
Flask and Werkzeug: Testing a post request with custom headers
Python - What type is flask.request.files.stream supposed to be?
You send the files as the parameter named file, so you can't look them up with the name file[]. If you want to get all the files named file as a list, you should use this:
upload_files = request.files.getlist("file")
On the other hand, if you really want to read them from file[], then you need to send them like that:
scc.data['file[]'] = # ...
(The file[] syntax is from PHP and it's used only on the client side. When you send the parameters named like that to the server, you still access them using $_FILES['file'].)
Lukas already addressed this,just providing these info as it may help someone
Werkzeug client is doing some clever stuff by storing requests data in MultiDict
#native_itermethods(['keys', 'values', 'items', 'lists', 'listvalues'])
class MultiDict(TypeConversionDict):
"""A :class:`MultiDict` is a dictionary subclass customized to deal with
multiple values for the same key which is for example used by the parsing
functions in the wrappers. This is necessary because some HTML form
elements pass multiple values for the same key.
:class:`MultiDict` implements all standard dictionary methods.
Internally, it saves all values for a key as a list, but the standard dict
access methods will only return the first value for a key. If you want to
gain access to the other values, too, you have to use the `list` methods as
explained below.
getList call looks for a given key in the "requests" dictionary. If the key doesn't exist, it returns empty list.
def getlist(self, key, type=None):
"""Return the list of items for a given key. If that key is not in the
`MultiDict`, the return value will be an empty list. Just as `get`
`getlist` accepts a `type` parameter. All items will be converted
with the callable defined there.
:param key: The key to be looked up.
:param type: A callable that is used to cast the value in the
:class:`MultiDict`. If a :exc:`ValueError` is raised
by this callable the value will be removed from the list.
:return: a :class:`list` of all the values for the key.
"""
try:
rv = dict.__getitem__(self, key)
except KeyError:
return []
if type is None:
return list(rv)
result = []
for item in rv:
try:
result.append(type(item))
except ValueError:
pass
return result