Category: django

Displaying a network chart graph diagram on a Django site

There is often a case for improving the understanding of things with visualisations.
Python provides a number of libraries to create great visualisations - however they often are focused more on a data science approach - scripts and jupyter notebooks.

What we want is the visualisations to be easily accessible through a django website, that is what I will be showing in this post with a specific focus on network diagrams.

What Visualisation Package are we using for the Network Graph

I have tried to find a few packages for creating a network graph:

Compararison

I will be using graphviz and networkx for very simple rudementary network graphs. You can make them look good but it is strenuous effort.

I will let you try networkx with plotly and igraph on your own.

Graphviz

Graphviz was very simple output and input. Not too much fuss and can render in many formats. To create a simple graph displayed on the frontend as an SVG:

from graphviz import Graph

g = Graph(
    'G',
    format='svg',
    engine='twopi',
)

g.node('root', shape='rectangle', width='1.5')
g.node('red')
g.node('blue')

g.edge('root', 'red', label='to_red')
g.edge('root', 'blue', label='to_blue')

context_data['my_chart'] = g.pipe().decode('utf-8')

Display on frontend:

{{ my_chart | safe }}

The image output:

graphviz-simple-radial-django

NetworkX

NetworkX is not primarily a graph drawing package but basic drawing with Matplotlib as well as an interface to use the open source Graphviz software package are included.

The networkx plot is drawn using matplotlib (it can also use graphviz) to draw.

    import matplotlib.pyplot as plt
    import networkx as nx
    import io

    G = nx.Graph()

    # rectanle width 1.5
    G.add_node('root')
    G.add_node('red')
    G.add_node('blue')

    # label: to_red
    G.add_edge('root', 'red')
    # label: to_blue
    G.add_edge('root', 'blue')

    nx.draw(G)
    buf = io.BytesIO()
    plt.savefig(buf, format='svg', bbox_inches='tight')
    image_bytes = buf.getvalue().decode('utf-8')
    buf.close()
    plt.close()

    context_data['my_chart'] = image_bytes

Display on frontend:

{{ my_chart | safe }}

The image output:

networkx-simple-django-network

No annotations...

Make sure you close the plot otherwise it will cause issues, matplotlib is not thread safe...

Important:

  • nx.draw(G) - draws with no labels
  • nx.draw_networkx(G) - Draws with labels

networkx-with-labels

How to fix Django OperationalError /admin/auth/user/add/ SAVEPOINT …_x1 does not exist

This is a weird one, an error I had never got until I used an external MySQL (Maria) DB Instance with Django.

The steps to recreate this error would be:

  1. As an Admin try and add another user from the admin section

You will get an error like this:

OperationalError /admin/auth/user/add/
error(1305, 'SAVEPOINT s139787825936192_x1 does not exist')

In my case the system had the following attributes:

  • CentOS 7
  • python mysql connecor: mysqlclient
  • django 2.2.15
  • Server version: 5.5.30 (ProxySQL)

According to this stackoverflow post on the subject, it was to do with the MySQL-Python connector.

The answerer recommends using the mysqlclient python package. Thing is...I am using it.

What I Tried

  • Upgrading to django 3
  • Downloading and installing the lastest python MySQL connectors
  • Installing mariadb libs locally on the app server
  • Uninstall mysqlclient package and use pip install PyMySQL
  • Downgrade from mysqlclient==2.0.0. to mysqlclient==1.4.6

What Worked

I moved to using a local database:

Server version: 10.5.4-MariaDB MariaDB Server

Using django-oauth-toolkit for Client credentials Oauth Flow

I've been wanting to secure my api - so unidentified and unathorized parties cannot view, update, create or delete data.
This api is internal to the company and will only be used by other services - in other words no end users.
Hence the delegation of authorization need not happen and the services will be authneticating directly with the api.

That is why the Oauth client credentials flow is used - it is for server to server communication. (As far as I know)

There is alot of conflicting information on Oauth but in the RFC6749 on Oauth 2 Client credentials is mentioned:

1.3.4.  Client Credentials

   The client credentials (or other forms of client authentication) can
   be used as an authorization grant when the authorization scope is
   limited to the protected resources under the control of the client,
   or to protected resources previously arranged with the authorization
   server.  Client credentials are used as an authorization grant
   typically when the client is acting on its own behalf (the client is
   also the resource owner) or is requesting access to protected
   resources based on an authorization previously arranged with the
   authorization server.

Nordic API's: Securing the API Stronghold book mentions:

Oauth: It’s for delegation, and delegation only

I agree except when the client is the resource owner in the client credentials instance.
In that case surely there is no delegation?

Should we use it

What is the advantage over a basic auth or token authentication method?

It seems to just be an added step for the client but the key is that the token expires. So if a bad actor gets our token it will not last long before it is of no use.
The client id and secret is the thing that is used to generate tokend for future calling of the api.

Difference between Resource Owner Password Based flow and client Credentials

Django-oauth-tollkit provides both and their example uses the resource owner password based flow.
In both cases the resource owner is the client - so there is no delegation.

So what is the difference?

I checked on stackoverflow, and it turns out I was wrong.

In the resource owner client based way, the resource owner (end user) trusts the client application enough to give it it's username and password.
We don't really want this.

Implementing Client Credentials flow

Since users are not going to use the API and only services/clients will, I want to disable the other authorization flows and disable registering of clients.

I will manage the clients and they will be the resource owners.

So if you follow the information in the django-oauth-toolkit and setting it up for client credentials that should help

Permissions are significantly different from Django Permissions

What I found out durinng testing is that OauthToolkit implements it's own seperate permissions. So if you were wanting to use django model permissions (add, change, view and delete), you don't be able to.

Wait...I spoke too fast.

You can allow this with:

permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoModelPermission]

However that means that you actually have to test with scopes if you expect a client to use it with Oauth and not django auth.

This is the view to use ClientProtectedResourceView