I'm building a webapp for a personal project and I'd like to be able to serve JSON to api calls and HTML to websites.
My code is pretty similar to this:
class TestAPI(Resource):
def get(self):
return {'hello': 'world'}
def post(self):
data = request.form["data"]
result = do_something(data)
return {'result': result}
@mod.route("/")
def test():
return render_template("test.html")
@mod.route("/do_something", methods=['GET','POST'])
def analyzer():
form = TestForm()
if request.method == 'POST':
data = request.form.get("data")
result = do_something(data)
return render_template("result.html", result=result)
return render_template("do_something.html", form=form)
I was hoping this would let a user navigate to the page and submit data in a form, have the data manipulated, and returned in another html page (using jinja templates). I was hoping it would also let a user curl the endpoints to do the same thing, except just getting JSON values back.
It seems like what happens depends on the order in which I define things:
from app.views.test import test
api.add_resource(TestAPI, '/do_something')
When it's set up like this, I get HTML from everything (in browsers and even from curl). If I reverse it, I get JSON everywhere. Is there a way for me to get both? (HTML in browser, JSON otherwise)
I would say in your backend, check the 'User-Agent'
parameter in the header of the request. If its a browser, return the html template. If it is an API, return json.
Credit to Piotr Dawidiuk
The above solution is not the most elegant way to do it. The accept
attribute is more appropriate for determining json or html.
The Accept request-header field can be used to specify certain media types which are acceptable for the response. Accept headers can be used to indicate that the request is specifically limited to a small set of desired types, as in the case of a request for an in-line image.