[django] Sending matplotlib generated figure(s) to django web app

This post introduces how to serve the figures generated by matplotlib to django web app without saving on the server.

In your django views py file, import the following libraries

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

from io import BytesIO
import base64

Note: the two lines of code above in blue need to be placed at the very beginning of the py script; otherwise, you would meet the following error: _tkinter.TclError: no display name and no $DISPLAY environment variable.

In the views py file, in the function that you defined to pass the image data to the front end template file, add the following code:

buf = BytesIO()
plt.savefig(buf, format='png', dpi=300)
image_base64 = base64.b64encode(buf.getvalue()).decode('utf-8').replace('\n', '')
buf.close()

Note: in the function that you defined to pass the image data to the front end template file in your views py file, remember to send the value of the variable image_base64 via, for example, json.

Now, in your front end template file, you can add the following image tag.

<img src="data:image/png;base64,{{image_base64}}" alt="some text to display to your users when the image does not show correctly" width=500 height=auto />

You now should be able to see the figure displayed on your web app page:)

For more details about using data url to pass image data to front end html file, check here (pdf).

 

 

How to Deploy a Django Application on a Server Running Ubuntu

This post provides tutorials on how to deploy a Django application on a server running Ubuntu.

Softwares needed to set up a server for Django application:

  • Virtualenv & Virtualenvwrapper / Conda
  • Django
  • Gunicorn
  • Nginx
  • Supervisor

Concept

Nginx will face the outside world. It will serve media files (images, CSS, etc.) directly from the file system. However, it can’t talk directly to Django applications; it needs something that will run the application, feed it requests from the web, and return responses.

That’s Gunicorn‘s job. Gunicorn will create a Unix socket, and serve responses to Nginx via the wsgi protocol – the socket passes data in both directions:

The outside world <-> Nginx <-> The socket <-> Gunicorn

All this family will live into a Virtualenv. Already wondered why Virtualenv is so useful when you develop Pythons’s applications? Continue to read and you will understand.

Before you start

References

I assume you have a server available on which you have root privileges. I am using a server running Debian 7, so everything here should also work on an Ubuntu server or other Debian-based distribution. If you’re using an RPM-based distro (such as CentOS), you will need to replace the aptitude commands by their yum counterparts and if you’re using FreeBSD you can install the components from ports.

Import CSV using Pandas to Django models

This post introduces how to import CSV data using Pandas to Django models.

Python has a built-in csv library, but do not use that, it is not flexible for csv data that has both string and number based data. See the reasons below:

builtin csv module is very primitive at handling mixed data-types, does all its type conversion at import-time, and even at that has a very restrictive menu of options, which will mangle most real-world datasets (inconsistent quoting and escaping, missing or incomplete values in Booleans and factors, mismatched Unicode encoding resulting in phantom quote or escape characters inside fields, incomplete lines will cause exception). Fixing csv import is one of countless benefits of pandas. So, your ultimate answer is indeed stop using builtin csv import and start using pandas.

Do not import the data in csv file to Django models via row by row method– that is too slow.

Django (version > 1.4 )  provides  bulk_create as an object manager method which takes as input an array of objects created using the class constructor.

See my example code below:

import pandas as pd

df=pd.read_csv('test_csv.txt',sep=';')

#print(df)

row_iter = df.iterrows()

objs = [

    myClass_in_model(

        field_1 = row['Name'],

        field_2  = row['Description'],

        field_3  = row['Notes'],

        field_4  = row['Votes']

    )

    for index, row in row_iter

]

myClass_in_model.objects.bulk_create(objs)

#Note: myClass_in_model: the class (i.e., the table you want to populate data from csv) we defined in Django model.py
#Note: field_1 to filed_4 are the fields you defined in your Django model.

 

References:

Import csv data into django models

How to write a Pandas Dataframe to Django model

Django bulk_create function example

Changing strings to Floats in an imported .csv