How to properly output JSON with app engine Python webapp2? - json

Right now I am currently just doing this:
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write('{"success": "some var", "payload": "some var"}')
Is there a better way to do it using some library?

Yes, you should use the json library that is supported in Python 2.7:
import json
self.response.headers['Content-Type'] = 'application/json'
obj = {
'success': 'some var',
'payload': 'some var',
}
self.response.out.write(json.dumps(obj))

webapp2 has a handy wrapper for the json module: it will use simplejson if available, or the json module from Python >= 2.6 if available, and as a last resource the django.utils.simplejson module on App Engine.
http://webapp2.readthedocs.io/en/latest/api/webapp2_extras/json.html
from webapp2_extras import json
self.response.content_type = 'application/json'
obj = {
'success': 'some var',
'payload': 'some var',
}
self.response.write(json.encode(obj))

python itself has a json module, which will make sure that your JSON is properly formatted, handwritten JSON is more prone to get errors.
import json
self.response.headers['Content-Type'] = 'application/json'
json.dump({"success":somevar,"payload":someothervar},self.response.out)

I usually using like this:
class JsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, ndb.Key):
return obj.urlsafe()
return json.JSONEncoder.default(self, obj)
class BaseRequestHandler(webapp2.RequestHandler):
def json_response(self, data, status=200):
self.response.headers['Content-Type'] = 'application/json'
self.response.status_int = status
self.response.write(json.dumps(data, cls=JsonEncoder))
class APIHandler(BaseRequestHandler):
def get_product(self):
product = Product.get(id=1)
if product:
jpro = product.to_dict()
self.json_response(jpro)
else:
self.json_response({'msg': 'product not found'}, status=404)

import json
import webapp2
def jsonify(**kwargs):
response = webapp2.Response(content_type="application/json")
json.dump(kwargs, response.out)
return response
Every place you want to return a json response...
return jsonify(arg1='val1', arg2='val2')
or
return jsonify({ 'arg1': 'val1', 'arg2': 'val2' })

Related

How do I decode a DRF response object's content to a Python String?

I have the following route in Django Rest Framework:
from rest_framework.viewsets import ModelViewSet
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
class MainViewset(ModelViewSet):
renderer_classes = [JSONRenderer]
authentication_classes = []
permission_classes = []
def alive(self, request):
return Response("API is Alive", 200)
I have a Django test that calls this API route, expecting the JSON string:
def test_base_route(self):
c = Client()
response = c.get('/budget/alive')
self.assertTrue(response.status_code == 200)
self.assertEqual(response.content.decode("UTF-8"), "API is Alive")
However, I get the following error:
def test_base_route(self):
c = Client()
response = c.get('/budget/alive')
self.assertTrue(response.status_code == 200)
> self.assertEqual(response.content.decode("UTF-8"), "API is Alive")
E AssertionError: '"API is Alive"' != 'API is Alive'
E - "API is Alive"
E ? - -
E + API is Alive
I find this strange since I decoded the string. I know it's a simple thing to trim off quotation marks, but what is the right way to serialize a single string as a response and get it back in the content of a response in DRF when sending JSON?
You can use .data for this case:
self.assertEqual(response.data, "API is Alive")

How to get a better formatted JSON Response in DjangoRestFramework UI

I have an APIVIEW in DRF which I have written some views in it to get some Response, I would like to get a better formatted JSONResponse.
Views.py
class Pay(APIView):
def get(self, request):
url = "https://api.paystack.co/transaction/verify/262762380"
payload = {}
files = {}
headers = {
'Authorization': 'Bearer SECRET_KEY',
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data= payload, files=files)
return Response(response)
This is a pictorial representation of the bad formatted JSONResponse I am getting which I would like to improve. Thanks
So in the case you don't have a Model but rather some data structure you get in some other way (as in a response from a third party API) just return a Response with this data structure as argument.
In this case you are effectively acting as a kind of proxy between the 3rd party API and your client, if that is what you intend (be sure not to leak private data!)
Example:
class Pay(APIView):
def get(self, request):
url = "https://api.paystack.co/transaction/verify/262762380"
payload = {}
files = {}
headers = {
'Authorization': 'Bearer SECRET_KEY',
'Content-Type': 'application/json'
}
# no need for 'data' and 'files' arguments with method GET
response = requests.get(url, headers=headers)
# do some validation, at least check for response.status_code
if response.status_code == 200:
data = response.json()
return Response(data)
There are many more possibilities when using the requests library.

Dynamic request of data from API endpoint in DjangoRestFramework

I am making some API calls from an external source but would like to make it dynamic instead of manually putting the reference number in my views in the DRF UI provided.
What I want is that in my DRF UI, I should have a field whereby when I enter a reference number, I should get the response from from the API, I am successfully doing this manually but I want to make it dynamic from the DRF UI.
I would also like to get a better formatted JSON Response in my DRF UI. An image is below to better explain what I meant
Views.py
class Paystack(APIView):
def get(self, request):
url = "https://api.paystack.co/transaction/verify/{{REFERENCE_NO}}"
payload = {}
files = {}
headers = {
'Authorization': 'Bearer SECRET_KEY',
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data= payload, files=files)
return Response(response)
def post(self, request):
url = "https://api.paystack.co/transaction/verify/{{REFERENCE_NO}}"
payload = {}
files = {}
headers = {
'Authorization': 'Bearer SECRET_KEY',
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data= payload, files=files)
return Response(response)
urls.py
from django.urls import path, include
from .views import *
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('paystack', Paystack, basename='paystack')
urlpatterns = [
path('paystack/', Paystack.as_view(), name='paystack'),
]
Presently, my DRF UI looks likes this,
If you want to be able to get reference_id in your DRF UI, you must either define a serializer and catch the value from that, or, you can define a URL pattern which asks for a reference ID.
You can do this
In urls.py
urlpatterns = [
path('paystack/<str:reference_id>', Paystack.as_view(), name='paystack'),
]
In your views.py
class Paystack(APIView):
def get(self, request, reference_id):
url = f"https://api.paystack.co/transaction/verify/{reference_id}"
payload = {}
files = {}
headers = {
'Authorization': 'Bearer SECRET_KEY',
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data= payload, files=files)
return Response(response)

How to send a file object from Flask API to Angular Frontend without storing it on the file system

I am trying send a file object of type BytesIO from flask API to angular frontend.
I am using json.dumps(). File object shouldn't be stored on file system. I am using memory for storing file object. Using io.BytesIO().
return json.dumps({'UserId': username, 'file': file_object}), 201
Typerror: <_io.BytesIO object> is not json searializable
You can use send_file with a file like object:
import io
from flask import send_file
#app.route("/send_file")
def send_file():
file = io.BytesIO()
file.write(b"Hello, World!")
file.seek(0)
return send_file(file, attachment_filename=f"example.txt", as_attachment=True)
And then I expect you'll do something with it in Javascript:
fetch('https://example.com/send_file')
.then(res => res.blob())
.then(blob => {
// Do something
});
http://blog.luisrei.com/articles/flaskrest.html
Please check this link and refer "RESPONSES" subtitle.
from flask import Response
#app.route('/hello', methods = ['GET'])
def api_hello():
data = {
'hello' : 'world',
'number' : 3
}
js = json.dumps(data)
resp = Response(js, status=200, mimetype='application/json')
resp.headers['Link'] = 'http://luisrei.com'
return resp

Storing JSON variable in django database

In my app that uses Gridster I am changing the widget positions and then saving it as a json variable.I want to store this json variable in django database.
For that I am not understanding how should I define a function in views.py and a class in models.py which can store the json variable
My HTML/JS template is
var URL = "{% url 'my_view_url' %}";
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
});
My views.py
def save_grid(request):
if request.method == 'POST':
# Some code to get json variable and store it to model
return HttpResponse('success') # if everything is OK
I want to write some kind of class in models.py corresponding to view.py so that JSON variable can be saved
Edit1
My models.py is
from django.db import models
from django.utils import timezone
from django.utils import simplejson as json
class update_grid(models.Model):
data = JSONField(null=True, blank=True)
I just want to send data from views to this model(If it is correct)
Edit 2
My JS Script is updated as follows
var URL = "{% url 'save-grid' %}";
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(updated_grid){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
updategridster(updated_grid);
});
Now I get this error
POST http://localhost:8000/calendar_grid/save-grid net::ERR_CONNECTION_ABORTED jquery.min.js:2
You have the built in JSONField if you use PostgreSQL.
Otherwise there are several implementations like django-jsonfield, for admin i pair this with django-jsoneditor
Then you can save the JSON data in a single field, and in the case of the built in, you can even do queries/filter on specific keys inside the JSON structure.