Best practices to combine REST API with web interface using FLASK - python

I currently build a web application using flask, sqlalchemy and jinja2.
To get a proper web interface, I build my views as follows:
#app.route('/mydata/', methods=['GET'])
#login_required
def mydata_list():
# build data here...
return render_template('mydata/index.html', data=data))
Now, if I need to build a REST API, I am supposed to terminate with
return jsonify(data)
So, how to handle this to avoid code duplication? Is it a good practice to add a ?api=True to my url, test it in my view, then return appropriate answer?

There is really no right or wrong way to do this, more so with Flask, which is a framework that imposes so few rules on the developer.
If you want my opinion, I think using the same set of view functions for web site and API leads to code that is harder to maintain, because there are a few significant differences between the two, for example:
Authentication: this is typically done in very different ways for web vs. API.
Content: for the API you just return data, but for a web page the view function may need to do more work and obtain extra data that is only needed for rendering the template.
Request methods: APIs use more HTTP request methods than web apps. For example, to delete a resource through an API the client normally sends a DELETE request. A web application running on a web browser needs to do everything with GET and POST requests. Also, the POST request method has different usages in APIs vs. web apps.
My recommendation is that you make your view functions for both APIs and web apps very thin and put the business logic of your application in common classes that both sets of view functions can invoke.

If you want to use the same endpoint for serving a template as well as JSON data, you can test whether this is an AJAX request with request.is_xhr. For example:
#app.route('/numbers/')
def numbers():
data = [1, 2, 3]
if request.is_xhr:
return jsonify(data=data)
return render_template('numbers.html', data=data)

Related

Flask redirect alternative in Seldon core

I have a kibana dashboard where there are some links provided for the user to click on. The link calls a flask service, which does some processing and redirects an URL using flask's redirect API, so that Kibana dashboard shows the processed values. Now, the flask is replaced with seldon core for predictions. Is there any way to redirect an URL, like it can be done in flask?
Thanks in advance.
Have you completely removed the flask app? If not you can use the flask to handle all interactions with the frond end and just use Seldon for the predictions.
This is a micro-services approach. You can receive the request as you used to in flask and then from within flask call the Seldon micro-service, get the prediction and then redirect to the results page with the new results from within flask.
This is good because if you change your prediction logic or tools in the future you wont have to redo all this work. You ll just change the function that flask calls to get the results. Also you frond end and back-end will be agnostic of the implementation details of the prediction method.

Simple Web API with no views or models in Django Rest Framework

What I need is simple: a piece of code that will receive a GET request, process some data, and then generate a response. I'm completely new to python web development, so I've decided to use DRF for this purpose because it seemed like the most robust solution, but every example I found online consisted of CRUDs with models and views, and I figure what I need is something more simple (since the front-end is already created).
Could anyone provide an example on how to do this on DRF? (or even some other viable solution, having in mind that it needs to be robust enough to take on multiple requests at the same time in production)
Simple way to do thing you want is by using Django REST Framework's APIView (or #api_view decorator).
Here is an example of it in the docs: https://www.django-rest-framework.org/api-guide/views/.
Besides code on that page, you would need to register your view on appropriate route, which can be found here: https://www.django-rest-framework.org/api-guide/routers/
Django and Django REST Framework are pretty heavy products out-of-the-box.
If you want something more lightweight that can handle many incoming requests, you could create a simple Express server using Node.js. This would result in very few lines of code on your end.
Sample Node server:
var express = require('express')
var app = express()
app.get('/', (req, res) => {
res.send('hello world')
});
app.listen(8000);
For DRF:
https://www.django-rest-framework.org/tutorial/quickstart/
Another viable option:
Flask:
https://flask.palletsprojects.com/en/1.1.x/quickstart/

Django and React

I haven't been able to locate anything saying one way or the other, but does anyone know if you can have function based views in django and have react as your frontend? No use of templates.
If so, would it look like this?
# fad index route
def fad_index(request):
context = {'fads': Fad.objects.all()}
return render(request, 'fad/fad_index.html', context)
But instead of fad_index.html, would it just be the route that you want it to take in react?
When you use Django views, whether class or function based, you are required to render html responses, so there is no point on using React this way since the front-end functionality is already embedded in the html you are rendering.
React is thought for creating front-end applications that run independently from the back-end application. For that, the back-end application must provide specific url points for fetching or posting data from and to the front-end. These url points are known as end-points, and this back-end architecture is known as API, and come in two main flavors, SOAP and REST, and differ, basically, in the format of the data that comes from and goes to the front-end. SOAP APIs use xml, and REST APIs use json.
If you have a REST API back-end, you can use ajax in a React front-end to fetch and post data from and to the back-end's end-points.
For making a REST API back-end using Django, you need to complement it with another library called Django Rest Framework, that allows Django views to render json packages instead of html, so your React front-end can use these end-points.
React is simply a component composition library. You can use it to render single components on a web page or as the rendering layer of a more complex Single Page Application (SPA)
The general best practice when creating single page applications is to send the data over in a JSON format using a REST API. JSON because it can be parsed in almost any language and REST because the server should not care what the client is specifically doing.
There is a module called django rest framework that allows you to return raw data from REST style endpoints in a JSON format.

Authentication on App Engine / Python / Django non-rel over JSON

I'm building a site on Google App Engine, running python and Django non-rel. Everything is working great for HTML and posting/reading data. But as I'm moving forward I'd like to do many of the updates with AJAX, and eventually also over mobile devices like Android and iPhone.
My pages use django non-rel and my login/logout authentication works great for the HTML. But update information sent over JSON would have to be authenticated that the user can make the changes. I see how doing authentication for just AJAX calls wouldn't be too difficult since your still hitting the website, but what about when throwing in mobile phone authentication?
So I'm new to this, where do I start?
How can I set up services on gae so I can do authenticated CRUD operations? Ideally I'd like to use the exact same REST services for ajax, android, etc.
Python makes this pretty easy, you can just create a decorator method of checking the auth and add the decorator to any method requiring auth credentials.
def admin(handler_method):
"""
This decorator requires admin, 403 if not.
"""
def auth_required(self, *args, **kwargs):
if users.is_current_user_admin():
handler_method(self, *args, **kwargs)
else:
self.error(403)
return auth_required
...
#admin
def crudmethod_update(self, *args, **kwargs):
...
Mind you, this assumes a few things about how you are grabbing user data and such but the principal is the same with any setup. The notion you may be laboring under is that ajax calls are handled somehow differently on the server, but just like any restful method you are really getting the same headers. If you can check the authentication on the standard html request you can quite literally hijack the form submission with an ajax request and get the same result back. You may want to get JSON back instead or a smaller piece of HTML and for that you want to either:
Add something you can check in the request to know that it is an ajax request and adjust accordingly.
Implement an RPC Model for handling ajax requests specifically.
For actually handling authentication you can use the google.appengine.ext users library and ride on the google accounts auth or you can write your own. Writing your own of course means implementing a session mechanism (for retaining state across the user session) and storing the passwords in a hashed and salted state for verification.

Web based wizard with Python

What is a good/simple way to create, say a five page wizard, in Python, where the web server component composes the wizard page content mostly dynamically by fetching the data via calls to a XML-RPC back-end. I have experienced a bit with the XML-RPC Python module, but I don't know which Python module would be providing the web server, how to create the static content for the wizard and I don't know how to extend the web server component to make the XML-RPC calls from the web server to the XML-RPC back-end to be able to create the dynamic content.
If we break down to the components you'll need, we get:
HTTP server to receive the request from the clients browser.
A URL router to look at the URL sent from client browser and call your function/method to handle that URL.
An XML-RPC client library to fetch the data for that URL.
A template processor to render the fetched data into HTML.
A way to send the rendered HTML as a response back to the client browser.
These components are handled by almost all, if not all, Python web frameworks. The XML-RPC client might be missing, but you can just use the standard Python module you already know.
Django and Pylons are well documented and can easily handle this kind of project, but they will also have a lot of stuff you won't need. If you want very easy and absolute minimum take a look at using juno, which was just released recently and is getting some buzz.
These frameworks will handle #1 and provide a way for you to specify #2, so then you need to write your function/method that handles the incoming request (in Django this is called a 'view').
All you would do is fetch your data via XML-RPC, populate a dictionary with that data (in Django this dictionary is referred to as 'context') and then render a template from the context into HTML by calling the template engine for that framework.
Your function will just return the HTML to the framework which will then format it properly as an HTTP response and send it back to the client browser.
Simple!
UPDATE: Here's a description of how to do wizard style multiple-step forms in Django that should help you out.

Categories

Resources