How do I convert Python POST data to JSON? - python

I have the following code in Python:
def post(self):
example = self.request.get("example")
other = self.request.get("other")
How do I get all post data if unknown? I'm very new to Python but something along the lines of:
def post(self):
array = self.request.get()
myJSON = MagicArrayToJson(array)
self.response.headers['Content-Type'] = 'application/json'
self.response.write(myJSON)

It may depend on the framework you use. But i suppose that there all have pretty same notation like self.request.data or self.request.body for post request.
Try self.request.data like this
def post(self):
data = self.request.data
# If data is in querystring, convert it to dict
# urlparse lib is convenient for this
myJSON = MagicArrayToJson(array)
self.response.headers['Content-Type'] = 'application/json'
self.response.write(myJSON)

Related

get parameters in a get request in django rest framework?

I want to get the parameters sent to my rest api
what I want is to obtain the parameters that to use them consume another api and return the response of the third party api
but in name and comic i get None
http://127.0.0.1:8000/searchComics/
{name:"3-D Man","comics":12}
this is my view
class MarvelApi(APIView):
def get(self, request):
private_key = "88958f2d87bd2c0c2fa07b7ea654bcdf9f0389b3"
public_key = "8d415ffcc9add56b0a47c0a7c851afc3"
ts = 1
md5_hash = "46ecbbd63108b0561b8778a57823bd34"
query_params = self.request.query_params
name = query_params.get('kword', None)
comic = query_params.get('comic', None)
end_point = f"https://gateway.marvel.com:443/v1/public/characters?ts={ts}&apikey={public_key}&hash={md5_hash}&name={name}&comic={comic}"
response = requests.get(end_point)
response_json = json.loads(response.text)
return Response(status=status.HTTP_200_OK, data=response_json)
I think the problem is these two lines
name = query_params.get('kword', None)
comic = query_params.get('comic', None)
that do not capture the values ​​correctly, do you know how to solve it?
You wanted to get them from GET method, but instead you gave a dictionary, so I guess you sent it via POST. Instead of posting dictionary you should go with url:
http://127.0.0.1:8000/searchComics/?name=3-D+Man&comic=12
And you had probably a typo. You had plural "comics" in dictionary and you seek for "comic" singular.
And if you want to have data with POST method, just change def get(...) to def post(...).

Get data from json form-data and store in database in django

My JSON file : (It's a file)
{ "user-id": 10009, "rating": 3, "movie_id": 9823 }
I need to get the each data separately.so I can store them in database. the JSON file is a form-data.
I tried:
def post(self, request):
data = request.FILES['json_file']
# a = data.read().decode('utf-8')
a = json.loads(data)
x = a['user-id']
print(x)
return Response(x, status=status.HTTP_201_CREATED)
The above code is not working and giving me error:
the JSON object must be str, not 'InMemoryUploadedFile'
How can i get data from JSON file(form-data) and store it's content in database?
data is of the type InMemoryUploadedFile, so to convert it to a string you need to read it (as bytes) and convert it to a string:
def post(self, request):
data = request.data.get('json_file')
a = json.loads(str(data.read()))
x = a['user-id']
print(x)
return Response(x, status=status.HTTP_201_CREATED)

Getting string instead of list when trying to get value of JSON response

I have the following JSON response:
{"response": [100, {"name": "Bill"}, {"name": "John"}]}
All I need is to iterate through the list.
So my plan is to get the list first and then iterate through it.
But when I tried to get the list with
list_dict.json().get("response")
I got the string:
100{"name": "Bill"}{"name": "John"}
How could I get the list?
UPDATE: Here is the related code views.py
from django.http import HttpResponse
from lib.api import Api
import requests, json
def verify(request):
api = Api(access_token=access_token)
list_dict = api.get_all(owner_id=owner_id)
result = list_dict.json().get("response")
return HttpResponse(result)
Here is the api.py
import requests
class Api:
def __init__(self, access_token='', **kwargs):
self.access_token = access_token
def get_all(self, owner_id=''):
api_url_template = 'http://api.example.com/method/get.All?owner_id={0}&access_token={1}'
api_url = api_url_template.format(owner_id, self.access_token)
response = requests.get(api_url)
return response
That's just the result of passing a list to HttpResponse. If you want to see the full response as a string, pass it as a string:
return HttpResponse(str(result))
Of course, to use it as a list within your code you don't need to convert it to a string, you can just use it as is.

Accessing response soap header using suds

I have a soap 1.1/1.2 web service I'm trying to access using suds.
Unfortunately the service puts authentication token in response soap header.
Is it possible to access the header somehow?
I know one can set a custom soap header in the request, but that's not what I'm looking for.
I've been using the (still maintained) suds-jurko branch, and ran into trouble because client.last_received() was removed early after it was forked. So I had to figure out an alternative way to access the headers.
Fortunately, you can use a message plugin to store the parsed document, and then later access the headers via the plugin. For added convenience, instead of working with raw values from the xml document, you can process the headers based on the service-method, to get a correctly typed/structured value.
from suds.plugin import MessagePlugin
class HeaderPlugin(MessagePlugin):
def __init__(self):
self.document = None
def parsed(self, context):
self.document = context.reply
def get_headers(self, method):
method = method.method
binding = method.binding.output
rtypes = binding.headpart_types(method, False)
envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
soapenv = self.document.getChild('Envelope', envns)
soapheaders = soapenv.getChild('Header', envns)
nodes = soapheaders.children
if len(nodes):
resolved = rtypes[0].resolve(nobuiltin=True)
return binding.unmarshaller().process(nodes[0], resolved)
return None
usage:
from suds.client import Client
hp = HeaderPlugin()
client = Client(wsdl, plugins=[hp])
response = client.service.LoremIpsum()
headers = hp.get_headers(client.service.LoremIpsum)
example output:
>>> headers
(AuthenticationResponseHeader){
sessionKey = "a631cd00-c6be-416f-9bd3-dbcd322e0848"
validUntil = 2030-01-01 01:01:01.123456+01:00
}
>>> headers.validUntil
datetime.datetime(2030, 1, 1, 1, 1, 1, 123456, tzinfo=<suds.sax.date.FixedOffsetTimezone object at 0x7f7347856be0>)
You can do something like
print client.last_received().getChild("soap:Envelope").getChild("soap:Header")
.getChild("ResponseHeader").getChild("resultCode").getText()
The above reads a field resultCode in the soap header. You have to do this for each field. This was a back door left to read headers as much as i know.
For details look at soap headers with suds
The Towr's class plugin works well, but it has a problem when do you have more then one obj in Soapheader Response.
His code get only the first object.
Here is the code to improvement the Towr's class:
class HeaderPlugin(MessagePlugin):
def __init__(self):
self.document = None
def parsed(self, context):
self.document = context.reply
def get_headers(self, method):
Result = {}
method = method.method
binding = method.binding.output
SHeaderElem = binding.headpart_types(method, False)
envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
soapenv = self.document.getChild('Envelope', envns)
soapheaders = soapenv.getChild('Header', envns)
SHeaderNodes = soapheaders.children
for Elem in SHeaderElem:
for Node in SHeaderNodes:
if(Node.name == Elem.name):
ElemRes = Elem.resolve(nobuiltin=True)
NodeRes = binding.unmarshaller().process(Node, ElemRes)
Result[Elem.name] = NodeRes
return Result
#
To understand better, see the example.
If do you receive this Soap Response:
<soap-env:Envelope xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<soap-env:Header>
<eb:MessageHeader eb:version="1.0" soap-env:mustUnderstand="1">
<!-- -->
</eb:MessageHeader>
<wsse:Security>
<!-- -->
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<!-- -->
</soap-env:Body>
</soap-env:Envelope>
The function get_headers will return a dict like this:
SoapHeadersResp = {'MessageHeader':MessageHeaderObj, 'Security':SecurityObj}
To use this class just follow the same steps that Towr said, replacing his HeaderPlugin class with this one.

Is there a better way to write this URL Manipulation in Python?

I'm curious if there's a simpler way to remove a particular parameter from a url. What I came up with is the following. This seems a bit verbose. Libraries to use or a more pythonic version appreciated.
parsed = urlparse(url)
if parsed.query != "":
params = dict([s.split("=") for s in parsed.query.split("&")])
if params.get("page"):
del params["page"]
url = urlunparse((parsed.scheme,
None,
parsed.path,
None,
urlencode(params.items()),
parsed.fragment,))
parsed = urlparse(url)
Use urlparse.parse_qsl() to crack the query string. You can filter this in one go:
params = [(k,v) for (k,v) in parse_qsl(parsed.query) if k != 'page']
I've created a small helper class to represent a url in a structured way:
import cgi, urllib, urlparse
class Url(object):
def __init__(self, url):
"""Construct from a string."""
self.scheme, self.netloc, self.path, self.params, self.query, self.fragment = urlparse.urlparse(url)
self.args = dict(cgi.parse_qsl(self.query))
def __str__(self):
"""Turn back into a URL."""
self.query = urllib.urlencode(self.args)
return urlparse.urlunparse((self.scheme, self.netloc, self.path, self.params, self.query, self.fragment))
Then you can do:
u = Url(url)
del u.args['page']
url = str(u)
More about this: Web development peeve.

Categories