chartjs_engine
aims to provide a django app that will produce chartjs
charts by instantiating a chart engine which renders the chart to a string of html and <script>
tags. This can be useful for making charts in whatever kind of pre-existing views you already
have.
If you have a blog app, you could write a model method that scans for custom chart markup and then inserts the html.
If you wish to create a chart based on django querysets, outside API calls, or anything else, just gather your data in a django view and pass it to the chart engine which can then be returned like a regular view.
pip install django-chartjs-engine
settings.py
INSTALLED_APPS = [
...
'chartjs_engine',
]
CHARTJS_SCRIPT = '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.bundle.min.js"></script>'
You must also add the chartjs
script to your html file somewhere. It has been
excluded from the template in order to allow it to be loaded exactly once. (Each
page may have multiple charts, and if it was included in the template it would load
once for every chart)
In order to include it in the response, it is best to put the script source in settings and then add it to the response later.
from django.http import HttpResponse
from chartjs_engine.views.engine import Engine
from django.conf import settings
def chart_view(request):
"""construct data form a source and send it to the chart engine"""
chart_setup = {
'chart_name': 'testchart',
'chart_type': 'line',
'chart_labels': ['the', 'labels'],
'options': 'options',
'datasets': {
'data1': [1, 2],
'data2': [3, 4],
}
}
engine = ChartEngine(**chart_setup)
chart = engine.make_chart()
return HttpResponse(settings.CHARTJS_SCRIPT + chart)
If you have a database object which is returned in a response (like a blog post) you can make some custom markup which can be substituted for chart html when the view is loaded.
CHARTJS_REGEX = re.compile(r'(\[chartjs\].*?\[/chartjs\])', re.DOTALL)
The above regular expression will capture everything in between and including
[chartjs]
and [/chartjs]
tags in the database.
Then, with the following model method, you could turn some markup (like the example below into a chartjs javascript chart...
[chartjs]
name: testchart
type: line
labels: the, labels
data-foo: 1, 2
data-bar: 3, 4
[/chartjs]
class BlogPost(models.Model):
"""A model that has everything needed for a blogpost"""
# All of the model fields would be here
...
def insert_chart(self):
"""
Finds the chartjs data by regex in a post and calls the function to
replace markup with chart javascript in the post.
"""
chart_data = {}
# re.DOTALL makes "." accept all characters. chart_data var is list of matches.
pattern = settings.CHARTJS_REGEX
#Finding all the chartjs markup and iterating to parse each one
markup_data = re.findall(pattern, self.post)
if markup_data:
# Adding the chartjs javascript library (exactly once) to the html
self.post = settings.CHARTJS_SCRIPT + self.post
for data in markup_data:
# Regex captures the "[chartsjs]" tags, omitting them...
data = data.split('\r\n')[1:-1]
# name and type are in list as "name: the-name" so split/strip whitespace
chart_data['chart_name'] = data[0].split(':')[1].strip()
chart_data['chart_type'] = data[1].split(':')[1].strip()
# Split label by item delimited by "," stripped of whitespace.
chart_data['chart_labels'] = [item.strip() for item in \
data[2].split(':')[1].split(',')]
chart_data['datasets'] = {}
# data[3:] is going to be chart data so split/strip and convert to json.
for data_set in data[3:]:
# split by ':', then [0] index will be the dataset title
d = data_set.split(':')
chart_data['datasets'][d[0]] = [item.strip() for item in \
d[1].split(',')]
# Left for future use, this may cause errors with chart specific
# options in views if changed
chart_data['options'] = 'options'
# Instantiate the ChartEngine and make the chart
engine = ChartEngine(**chart_data)
# replace 1 match in the post with the chart javascript
self.post = re.sub(pattern, engine.make_chart(), self.post, count=1)