Making things, writing code, wasting time...

Category: React

Adding a React frontend to your Flask project

Introduction:

Flask is great for quickly building server side application.
React is great for quickly building responsive user interfaces.

This post is part 2 of a 3 part series. I’m going to walk through setting up a Flask API project, adding a React frontend to the project and then adding some data visualization to the React frontend.

Here are the other sections:

  1. Adding an API to your Flask project.
  2. Adding a React frontend to your Flask project
  3. Adding data visualization to your Flask app with React Victory charts.

We’ll look at this from the perspective of a project that’s already in flight. As most people who are familiar with Flask, are already familiar with Miguel Grinbergs microblog application, I’ve cloned his project repository we will add a React frontend into it.

Flask and React work really well together:

With Flask we can:

  • Run server side scripts and applications.
  • Deliver generic HTML sections such as headers / footers / nav bar.
  • Deliver raw JSON data via API endpoints.
    • Make database connections and requests.
    • Data processing / computation and packing data.

With React we can:

  • React can build responsive, stateful components.
    • Any component that needs memory, (remembering viewport height / width for example).
    • Show / hide / update a div, or HTML section.
  • Build a responsive user interface.
    • Anything that changes or updates with user input
    • Handle onClick functions.
    • Extensive compatible library selection, such as drag and drop tools.

Why do we need JS?

Our goal is to create a modular application, with a seamless (as possible), user interface and user experience.

Normally with a Flask only application; if a user clicks on a link or refreshes some data – the entire HTML page is dumped, then all of the required data structures are regenerated on the server side, a HTML template is populated and reloaded in the users browser – this can take a long time from the users perspective.

In an ideal application – if a section of your app needed to be updated, your server would, asynchronously, resend the required data, then your application frontend would handle rerendering only the updated section.
Only the required <div> or HTML section would be updated – the rest of your webpage would remain unchanged. The user doesn’t see all of this magic happening in the background.

Create a modular application with JS and React
Create a modular application with JS and React

For example: if a user requested updated data for Chart 2 in the diagram above; we don’t want to regenerate the Navigation, Chart 1, and Page Content sections. We only want to update Chart 2, and have the data fetched in the background – so the user experience feels nice and smooth.

This is common practice in most client side applications but can become a bit tricky when you have a server side application.

Also if you’re like me and don’t have a background in Computer Science, you may not be aware that there is some additional optimization to be had in your applications.

Project structure:

Let’s build this from the Flask large application structure.

Here is the typical project structure for a Flask application.

Flask large application directory structure:

|   config.py
|   microblog.py
|
+---app
    |   cli.py
    |   models.py
    |   __init__.py
    |
    +---api_1_0
    |       routes.py
    |       __init__.py
    |
    +---main
    |       forms.py
    |       routes.py
    |       __init__.py
    |
    +---static
    |       loading.gif
    |
    +---templates
        |   base.html
        |   index.html
        |   user.html
        |
        \---errors
             404.html
             500.html

We’re going to add the React setup into the app/static folder.

Webpack and Babel:

While technically not required – these 2 tools make building a modern JavaScript frontend much easier.

We will, however, require Babel if we want to use React JSX (a syntax extension to JS, it looks like a mix of HTML and JavaScript). JSX simplifies much of the React development, so we want to use it.

Babel:

  • What is Babel?
    • Bable is a toolchain used to convert the latest versions of JavaScript code into backwards compatible code that all modern web browsers can understand.
  • Why do I need to use Babel?
    • Babel is required if you want to write React JSX (which we do).
An example of Babel transpiling new JS to browser compatible JS.
(Picture https://babeljs.io/ )

Webpack:

  • What is Webpack?
    • Webpack is an open source JavaScript module bundler.
    • It can also bundle HTML, CSS and images.
    • When used with the Babel loader Webpack and Babel will transpile your code.
  • Why do I need Webpack?
    • React components are usually split across multiple files – we want Webpack to bundle all of our JS files into 1, minimized, file.
Webpack bundles your JS, HTML, CSS and images.
Picture (https://webpack.js.org/ )

Frontend directory structure:

app/static:

│   package-lock.json
│   package.json
│   webpack.config.js
│
├───css
│       style.css
│
├───dist
│       bundle.js
│
└───scripts
        index.js
        Finance.js
        HelloWorld.js

Installing Webpack and Babel:

We’ll use Node Package Manager to initialise our project and install Webpack and Babel.

Initialise your project:

npm init

This will create your package.json file. You’ll be asked to input basic information, such as author name, project name, description, project repository URL.

If you already have a package.json file – npm init will install any dependencies in that file – similar to how running python -m pip install -r requirements.txt would work in a Python application.

Install Webpack and Webpack CLI:

npm i webpack --save-dev
npm i webpack-cli --save-dev

Install Babel:

We will want to install 4 things here:

  1. babel core: The Babel core transpiler.
  2. babel-loader: The Webpack loader for Babel.
  3. @babel presets-env: This transpiles newer JS code into browser compatible JS (ECMA Script 5).
  4. @bable presets-react: This transpiles our React code into browser compatible JS.
npm i @babel/core --save-dev
npm i babel-loader --save-dev
npm i @babel/preset-env--save-dev
npm i @babel/preset-react --save-dev

Creating the config files:

To use Webpack and Babel, we need to create 2 config files:

  1. package.json
  2. webpack.config.js

Create package.json:

When running npm init, we created a package.json file. In this file we are going to tell Webpack how to run our frontend server.

We will do that by adding the following scripts section, which tells NPM how to run the app:

"scripts": {
  "build": "webpack -p --progress --config webpack.config.js",
  "dev-build": "webpack --progress -d --config webpack.config.js",
  "watch": "webpack --progress -d --config webpack.config.js --watch"
},
Example scripts section from my package.json

Top tip:

webpack --help

Will print the Webpack help information, where you can read in detail about the above commands.

Create webpack.config.js:

Our webpack.config.js file is going to provide Webpack with information on how our project is structured. Let’s look at the main sections:

  1. entry“: This is the index.js file, that links all of our React code to the HTML frontent. We instantiate our React components here and attach them to the DOM.
  2. output“: This is the bundle.js file, Webpack and Babel will output. This is our transpiled code that we actually include in our HTML file.
  3. resolve“: We want Webpack and Babel to resolve all .js, .jsx files. (.jsx files are sometimes used when a developer wants to specifically show that these files are React specific – .js workes just fine for us).
  4. module“: We want to use the babel-loader, and exclude any packages in ./node_modules (where all of our installed packages are located).

app/static/webpack.config.js

See highlighted sections below:

const webpack = require('webpack');
const config = {
    entry:  __dirname + '/scripts/index.js',
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js',
    },
    resolve: {
        extensions: ['.js', '.jsx', '.css']
    },
 
    module: {
        rules: [
            {
            test: /\.(js|jsx)?/,
                exclude: /node_modules/,
                use: 'babel-loader'     
            }        
        ]
    }
};
module.exports = config;

More information:

Here are links to the files I used in my application:

Here is some useful documentation:

Note: In the extensions section of the webpack.config.js – we can add other file extensions, such as CSS or images – as long as we have the relevant Webpack loaders installed.

React:

Installing React:

Now that we have a project setup with Weback and Babel – we need to install React. We can use NPM to install React and React DOM.

npm i react react-dom [--save-dev]
  • react: This is the actual React library package – used to define and create your React components.
  • react-dom: This mounts your React component into a HTML DOM object (usually a blank <div>).
    • DOM refers to the Document Object Model.
    • Used to identify and access DOM elements.
    • Updates HTML elements with with React.DOM.render()

Note: We’ve installed both packages with 1 command. You don’t necessarily need to add –save-dev as these are required package and you’ll probable use React for other projects.

Creating our React Components:

Let’s start with the usual “Hello, World!” Example.

React “Hello, World!”:

For every React component we create, we need to do 2 things:

  1. Write the React JS code for that component.
  2. Create an instance of that component, in the index.js entry file (from our webpack.config.js).

Creating the HelloWorld.js component:

app/static/scripts/HelloWorld.js

import React from 'react';
 
class HelloWorld extends React.Component {
    render() {
        return (
            <h1>Hello, World!</h1>
        );
    }}
export default HelloWorld;

What is this code doing?:

  • importing the React module.
  • Creating (extending) a HelloWorld Class, from the React.Component class type.
  • Rendering a <h1> element with the text “Hello, World!”
    • When creating a React component – the render() function is the only function we are required to use.
  • Exporting the HelloWorld function, so it can be imported by our index.js file.

When creating the component, we populated the render() function, React components have several built in methods and these are defined in the React component lifecycle.

Attaching the HelloWorld component to the DOM:

Now that our component is created – we need some way of creating an instance of that component and attaching it to a DOM element of our application.

app/static/scripts/index.js

import React from "react";
import ReactDOM from "react-dom";
import HelloWorld from "./HelloWorld";
 
ReactDOM.render(<HelloWorld />, document.getElementById("react-root"));

Running our code:

Now, when we run “npm run build” or “npm run watch”, NPM will run Webpack and Babel, transpile our index.js and HelloWorld.js file and output a ./dist/bundle.js file.

Output from npm run watch

Adding React to our Flask application:

Now that we have the HelloWorld example completed, we want to hook that into our Flask application. In order to call our JS code, we need to update our Flask HTML templates with a <script> tag, pointing to our bundled JS code. There are 2 places we can do this:

  1. base.html: If we want every Flask HTML endpoint to use this code (recommended).
  2. Add to the footer of a specific template: If you don’t want every endpoint to call your React code.
    1. You may want to do this if you already have Flask templates (that extend base.html) populating nav bars, footers and other generic HTML code.

app/templates/base.html:

{% block app_content %}
 
<div id="react-root"></div>
 
<script src="{{ url_for('static', filename='dist/bundle.js') }}"></script>
{% endblock %}

What is this code doing?:

  1. {% block app_content %} creates a Jinja2 template, which is used by Flask to populate the HTML templates.
  2. Creating an empty <div> element with and ID attribute of “react-root”.
    • This matches the ID element our React.DOM.render() function is looking for.
  3. Adding the script tag with a link to our bundle.js file.

Viewing our React app in the browser:

Our Hello World app in progress:

Note: All the other Flask rendered elements, from the microblog application, are there, for example the nav bar and search bar. However, now we also have rendered our first React component.

There’s not much here yet – but it’s a start!

React API:

Now that we can render React components – we want to be able to populate these components, with data from our Flask API.

First, let’s look at the React documentation for the recommended methodology for adding API requests into React components.

Our API component:

class Finance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
    error: null,
    isLoaded: false,
    items: []
    };
  }
  componentDidMount() {
    fetch("/api_1_0/finance/1/2018")
    .then(res => res.json())
    .then(
      (result) => {
      this.setState({
        isLoaded: true,
        items: result.items
      });
      },
      (error) => {
      this.setState({
        isLoaded: true,
        error
      });
      }
    )
  }
  render() {
    const { error, isLoaded, items } = this.state
    if (error) {
    return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
    return <div>Loading...</div>;
    } else {
    return (     );
    }
  }
}

What is this code doing?:

  1. We’ve added a constructor():
    1. This stores the component state.
    2. Stores error and isLoaded status – used in the render() function.
  2. Added the componentDidMount() built-in function:
    1. This is a React component built in function – using this function allows us to populate the component state with the output of from the API.
    2. Update the fetch() URL with the required API endpoint.
    3. Update component state with this.setState.
    4. Update isLoaded and error status – depending on the response from the API.
  3. Updated the render() function.
    1. Now handles error status from the API.
    2. Also has a loading section – we could add a loading animation here for example.

Note: The below code is an example of JavaScript “destructuring“.

const { error, isLoaded, items } = this.state

The state variable is a JS Object type, with the keys “error”, “isLoaded” and “items”.

We are populating const variables from the values of each of these keys in the components state.

Storing our API data in the Components state:

Now that we can make an API call – we need some way of storing this in our React component.

Storing the API response:

After making the API request – we store the response in the components state:

  componentDidMount() {
    fetch("/api_1_0/finance/1/2018")
:
      (result) => {
      this.setState({
        isLoaded: true,
        items: result.items
      });
      },
:
:
  }

We can store the state here, immediately, as we are using the React componentDidMount() function to make the API call.

Note: componentDidMount() is a React built-in function, which is allows us to set the component state value.

Retrieving the data from state:

Now that we have the API data stored in the component state – we can retrieve it like so:

make_chart_data(items) {
        
    let my_data_list = [];

    my_data_list.push(items.q1_earnings)
    my_data_list.push(items.q2_earnings)
    my_data_list.push(items.q3_earnings)
    my_data_list.push(items.q4_earnings)

    return my_data_list;
}

We can create an array, my_data_list, and populate it with the quarterly earnings.

Calling the make_chart_data function:

Inside the render function, we can call the make_chart_data() function. Obviously – we only want to call this function if there are no errors and the application has finished loading – so we put the function call in the “else” condition, as below:

render() {
	const { error, isLoaded, items } = this.state;
if (error) {
	return <div>Error loading data.</div>;
} else if (!isLoaded) {
	return <div>Loading...</div>;
} else {
	// Populate chart data:
	const finance_data = this.make_chart_data(items);
	const finance_axis = ["Q1", "Q2", "Q3", "Q4"];
:
	return (
:
:
      )
}

Debugging your application:

Some (maybe) obvious tips for debugging your application.

Based on issues I’ve found and conversations I’ve had with other people.

Chrome developer tips:

Viewing your API data in the Chrome developer tools may seem obvious to some people but as a lot of us are self-learning – I thought I’d show some tips:

Open the Chrome or Firefox developer tools.

Right-click anywhere on the page, and select “inspect” to view the developer tools.

Printing the components State:

In the render() function – log the components state:

render() {
	console.log(this.state)
	const { error, isLoaded, items } = this.state;
:
}

You can view this in the developer tools Console section:

Viewing the console output
Viewing the console output.

Some things to look out for:

  • Has the component State been set correctly?
    • error should be: null
    • isLoaded should be: true
    • items should contain the API response.

Some other issues that caught me out:

  • Are the values and data types correct?
    • Are you expecting and integer or String value?
    • (in a previous iteration of code, I sent the earnings values – from the API – as Strings instead of integers).
    • JavaScript only throws an error if you specifically type check.
  • Are you comparing True == true?
    • Python syntax versus JavaScript syntax.
  • Uncaught TypeError: items.map is not a function
    • You are trying using map to loop through an object, instead of an array.
    • Did you mean to send an array from your API?

Conclusion:

We installed and configured Babel and Webpack for our project.

We successfully added a React frontend into a Flask application.

We can make API calls from our Flask data API to our React frontend.

Resources:

Part 3 – React Victory charts (coming soon) >

Next up, we’ll look at adding some data visualisation to our applications with the amazing React library – Victory charts

Adding an API to your Flask project

Introduction:

This post is part 1 of a 3 part series. I’m going to walk through setting up a Flask API project, adding a React frontend to the project and then adding some data visualization to the React frontend.

If you’ve seen any of my previous blog posts, I’ve discussed setting up SQL databases, using Redis databases, setting up dashboard applications – so the next natural step would be to discuss displaying some of this data I’ve ben hoarding.

Here are the other chapters:

  1. Adding an API to your Flask project.
  2. Adding a React frontend to your Flask project (this section).
  3. Adding data visualization to your Flask app with React Victory charts.

Flask is great for creating server side applications and API projects.

In this blog post, I’m going to discuss some of the basic principals of adding an API to an existing Flask project. As most people who are familiar with Flask, are already familiar with Miguel Grinbergs microblog application, I’ve cloned his project repository we will add an API endpoint to it.

Flask large application structure:

Here’s the project structure for a large Flask application (this is Miguels’ microblog application).

For this project – we will be adding in the app/api_1_0 folder and associated code. We’ll also update the config.py to attach the API routes to our app.

|   config.py
|   microblog.py
|
+---app
    |   cli.py
    |   models.py
    |   __init__.py
    |
    +---api_1_0
    |       routes.py
    |       __init__.py
    |       load_junk_data.py
    |
    +---main
    |       forms.py
    |       routes.py
    |       __init__.py
    |
    +---static
    |       loading.gif
    |
    +---templates
        |   base.html
        |   index.html
        |   user.html
        |
        \---errors
             404.html
             500.html

Python data structures:

Let’s look at some Python dictionary data structures and I’ll show how I would add these to an SQL database. We’ll start off with a generic data structure.

Here we have a data structure (a Python dictionary), detailing information of some type of company. The Company dictionary contains a key “FINANCE”, which contains a list of Finance dictionaries.

{
    "BUSINESS_TYPE": "Manufacturing",
    "COMPANY": "Stark Industries",
    "COMPANY_CEO": "Pepper Potts",
    "FINANCE": [
        {
            "Q1_EARNINGS": 7825000000.0,
            "Q2_EARNINGS": 7825000000.0,
            "Q3_EARNINGS": 7825000000.0,
            "Q4_EARNINGS": 7825000000.0,
            "YEAR": 2018
        },
        {
            "Q1_EARNINGS": 7825000000.0,
            "Q2_EARNINGS": 7825000000.0,
            "Q3_EARNINGS": 7825000000.0,
            "Q4_EARNINGS": 7825000000.0,
            "YEAR": 2017
        },
        {
            "Q1_EARNINGS": 7825000000.0,
            "Q2_EARNINGS": 7825000000.0,
            "Q3_EARNINGS": 7825000000.0,
            "Q4_EARNINGS": 7825000000.0,
            "YEAR": 2016
        },
        {
            "Q1_EARNINGS": 7825000000.0,
            "Q2_EARNINGS": 7825000000.0,
            "Q3_EARNINGS": 7825000000.0,
            "Q4_EARNINGS": 7825000000.0,
            "YEAR": 2015
        }
    ]
}

Once we define the data structure, the next step for a Python developer would be looking at how to nest several Company dictionaries, inside another wrapper dictionary.

What use would our database be if we can only store 1 company – we want to be able to store data for a huge amount of companies – the more the better 🙂

{
    "DATA": [
        {
            "BUSINESS_TYPE": "Manufacturing",
            "COMPANY": "Stark Industries",
            "COMPANY_CEO": "Pepper Potts",
            "FINANCE": […
            ]
        },
        {
            "BUSINESS_TYPE": "Multinational Conglomerate",
            "COMPANY": "WayneCorp",
            "COMPANY_CEO": "Bruce Wayne",
            "FINANCE": [ …
            ]
        }
    ]
}

SQL Alchemy:

In SQL terms our Company dictionary is an example of a one-to-many relationship. 1 Company contains many Finance dictionaries.

One-to-many relationship.

Let’s look at how we would create this data structure with SQL Alchemy.

Creating the Company table:

The actual database connections are made in the config.py file – I’ve discussed this here before.

To add a database table, we create a class in the app/models.py file – we can then create instances of that class in our code.

I am loading the Python dictionaries via a function called load_junk_data – I wish I’d thought of a more professional name for this file but here we go:

app/models.py

class Company(db.Model):
    __tablename__ 	= 'company'
    id 			= db.Column(db.Integer, primary_key=True)
    name 		= db.Column(db.String(140))
    company_ceo 	= db.Column(db.String(140))
    business_type 	= db.Column(db.String(140))
    finances 	= db.relationship('Finance', backref='finance', lazy='dynamic')
 
    def __repr__(self):
        return '<Company {}>'.format(self.name)

What is this code doing?:

  • We are creating a class object named “Company”:
    • The Company class inherits the properties of the db.Model parent class.
  • We are giving the class a table name of “company”.
    • The SQL table “company” will be created when db.create_all() is called in config.py
  • The “id” column will be the primary key.
  • We are defining a “finances” column, which is a database relationship type:
    • It has a back reference to the “finance” table (we will make this next).
    • Setting the parameter lazy=dynamic is a dynamic loader, this will return a Query object when we call the filter() function.

Adding the Company object:

Now that we have created the table – how do we populate the data? Let’s create an instance of the Company object and store it in our SQL database.

Creating an instance of the Company object:

app\api_1_0\load_junk_data.py

my_wayne_company = Company(
	name		= company_waynecorp["COMPANY"],
	company_ceo	= company_waynecorp["COMPANY_CEO"],
	business_type	= company_waynecorp["BUSINESS_TYPE"]
)

First we populate the “my_wayne_company” object from our Company dict.

Adding a Company item to the database:

Now we can add the object into the database.

db.session.add(my_wayne_company)
db.session.commit()

Adding the Finance object:

Now that we have saved a Company object – we need to create some Finance objects and attach the finance data to their respective companies. The Finance table will represent the “many” part of our one-to-many relationships.

Creating an instance of the Finance object:

app/models.py

class Finance(db.Model):
    __tablename__    = 'finance'
    id 	             = db.Column(db.Integer, primary_key=True)
    year 	     = db.Column(db.Integer, default=1999)
    q1_earnings      = db.Column(db.Float)
    q2_earnings      = db.Column(db.Float)
    q3_earnings      = db.Column(db.Float)
    q4_earnings      = db.Column(db.Float)
   company_id        = db.Column(db.Integer, db.ForeignKey('company.id'))
 
    def __repr__(self):
        return '<Finance {}>'.format(self.id)

What is this code doing?:

  • We are creating a Finance class object:
    • The Finance class inherits the properties of the db.Model parent class.
  • We are giving the class a table name of “finance”.
    • We have previously defined this reference in the Company tables’ “finances” column.
  • We are defining a “company_id” column, which is an integer type:
    • “company_id” is a also a foreign key referencing the “id” column of the “company” table.

Adding a list of Finance items to the database:

Each Company object will have many Finance objects attached to it.

We can can create 2 instances of the Finance object, in a similar way to how we created an instance of the Company objects.

app\api_1_0\load_junk_data.py

wayne_finance_y1 = Finance(
	year		= wayne_finance_y1["YEAR"],
	q1_earnings	= wayne_finance_y1["Q1_EARNINGS"],
	q2_earnings	= wayne_finance_y1["Q2_EARNINGS"],
	q3_earnings	= wayne_finance_y1["Q3_EARNINGS"],
	q4_earnings	= wayne_finance_y1["Q4_EARNINGS"]
)

wayne_finance_y2 = Finance(
	year		= wayne_finance_y2["YEAR"],
	q1_earnings	= wayne_finance_y2["Q1_EARNINGS"],
	q2_earnings	= wayne_finance_y2["Q2_EARNINGS"],
	q3_earnings	= wayne_finance_y2["Q3_EARNINGS"],
	q4_earnings	= wayne_finance_y2["Q4_EARNINGS"]
)

These Finance objects can be attached to the Company object – in a similar way to appending items to a list.

my_wayne_company.finances.append(wayne_finance_y1)
my_wayne_company.finances.append(wayne_finance_y2)

Bonus points: Attach a list of Finance objects directly to the Company object.

In the previous section we had a Company object and then attached some Finance objects to it.

What if we already had several Finance objects – before we realised we needed to create a Company table? (I came across this problem recently – and it took me a bit of time to figure a clean way to do it).

Let’s look at adding a list of Finance objects directly to a Company object.

First we can create a series of Finance objects, in the same way as before:

app\api_1_0\load_junk_data.py

stark_finance_y1 = Finance(
    year        = stark_finance_y1["YEAR"],
    q1_earnings = stark_finance_y1["Q1_EARNINGS"],
    q2_earnings = stark_finance_y1["Q2_EARNINGS"],
    q3_earnings = stark_finance_y1["Q3_EARNINGS"],
    q4_earnings = stark_finance_y1["Q4_EARNINGS"]
)
:
stark_finance_y4 = Finance(
    year        = stark_finance_y4["YEAR"],
    q1_earnings = stark_finance_y4["Q1_EARNINGS"],
    q2_earnings = stark_finance_y4["Q2_EARNINGS"],
    q3_earnings = stark_finance_y4["Q3_EARNINGS"],
    q4_earnings = stark_finance_y4["Q4_EARNINGS"]
)

With these 4 Finance objects created – we can create a list of Finance objects:

finance_list = [stark_finance_y1, stark_finance_y2, stark_finance_y3, stark_finance_y4]

Now that we have the finance_list created – we can create the Company object:

my_stark_company = Company(
    name            = stark_company["COMPANY"],
    company_ceo     = stark_company["COMPANY_CEO"],
    business_type   = stark_company["BUSINESS_TYPE"],
    finances        = finance_list
)

We can add the list of Finance objects directly into the object instantiation.

db.session.add(my_stark_company)
db.session.commit()

Finally, add them to the database.

Viewing our SQL data:

When you view your data in an SQL database browser you will see something like this – first let’s look at the “company” table:

Viewing the “company” table in the SQLite browser.

Above we can see there are 2 Company objects in our “company” table.

Next, let’s look at the “finance” table:

Viewing the “finance” table in the SQLite browser.

We can see there are now, 6 Finance objects stored in the “finance” table, the “company_id” column is the foreign ID , which references the respective Company ID of each Finance object.

SQL data browsers:

There are lots of programs you can use to view your SQL database:

(This is not an advertisement, let me know if you have any better suggestions)

(Also let me know if you want to advertise 😛 )

Blueprints.

Flask Blueprints provide a means to section off your application. They are used to organise your application into distinct components.

A common application pattern is to section your application into 3 distinct parts:

  1. Authorized endpoints:
    1. Returns a HTML page: Login required.
  2. Unauthorized endpoints:
    1. Returns a HTML page: Login not required.
  3. API endpoints:
    1. Returns a (usually) JSON response: Login can be required.

Adding Blueprints to your Flask project:

To use Blueprints in your app you need to first create the Blueprint and then attach it to your app.

Create Blueprint:

app/api_1_0/__init__.py

from flask import Blueprint
 
bp = Blueprint('api', __name__)
 
from app.api_1_0 import routes

What is this code doing?:

  • Importing Blueprint from the flask package.
  • Creating an instance of the Blueprint object.
  • Importing the API endpoints from the routes.py file in the api_1_0 folder.

Attach the Blueprint to your app:

app/__init__.py

def create_app(config_class=Config):
    app = Flask(__name__)
    # Rest of your config goes here:
 
    from app.api_1_0 import bp as api_bp
    app.register_blueprint(api_bp, url_prefix='/api_1_0')

What is this code doing?:

  • In the create_app function, (used to instantiate our application).
  • We register the api_bp Blueprint with the app context.
    • We’re adding a URL prefix of “/api_1_0” to this Blueprint.

Adding an API endpoint to a Flask app:

Create an API endpoint:

We’ve created the Blueprint – now lets create the api_1_0 routes file and our first API endpoint.

app/api_1_0/routes.py

First, import the Blueprint object:

from app.api_1_0 import bp

Now we can create the API endpoint:

@bp.route('/get_company/<int:id>')
@login_required
def get_company(id):
    c = Company.query.filter_by(id=id).first_or_404()
    message = "Welcome to the API :)"
    content = {
        "name"          : c.name,
        "ceo_name"      : c.company_ceo,
        "business type" : c.business_type
    }
    status_dict = {
        "status": 200,
        "success": True,
        "message": message,
        "contentType":'application/json',
        "content": content
    }
 
    return jsonify(status_dict), status_dict["status"]

What is this code doing?:

  • @bp.route(‘/get_company/<int:id>’)
    • This is the Blueprint decorator.
    • binds the route to our API blueprint.
    • The route takes a parameter, an integer called “id”
  • Login is required to access this route.
  • c = Company.query.filter_by(id=id).first_or_404()
    • We query the database, for the first item matching the id value.
    • If no items match – we return a 404 response.
    • The response from the SQLAlchemy query is stored in “c”
  • content = {}
    • We populate a dictionary object with the result of the query.
  • status_dict = {}
    • We populate a return response.
    • HTTP status code 200.
    • Success = True.
    • A meaningful success message in the response.
    • A contentType, to notify other applications we are returning a JSON resonse.
    • We populate the “content” key with the dictionary object from the database response.
  • return jsonify(status_dict), status_dict[“status”]
    • We convert the Python dict “status_dict” into a JSON object.
    • We return the status_dict JSON object and the the HTTP code.

Note: We’ve defined the route as “/get_company/id” but we’ve also added the prefix “/api_1_0” to the Blueprint – so the actual endpoint will be: /api_1_0/get_company/1 (for company ID 1).

Viewing the API respone:

With the server running, we can view the API JSON response in a web browser.

Note:

  • The API Blueprints URL’s are prepended with “/api_1_0”.
  • The Company ID “1” relates to WayneCorp.

Conclusion:

We looked at some Python data structures and turned these into a SQL relational data structure.

We have successfully created a Flask API, which will pull data from our database and return it as a JSON response.

We can now use this API to serve external applications or a Javascript frontend to our applications.

Resources:

Part 2 >

We’ll build on our Flask project by adding a React frontend.

© 2024 Allyn H

Theme by Anders NorenUp ↑