Polling demand for Pycha charts
I’ve been looking over my statistics for the past few months on this blog and it quickly becomes apparent that the most sought after item is in fact the Pycha charts post. ( http://www.robvennikfotografie.nl/jvennik/?p=69 )
Seeing as I wrote it roughly a month after I was introduced to the whole Django situation, I pondered the idea of rewriting the post with the knowledge I posses now to form a better resource for those of you looking to implement a chart system. So if you’re interested in the above, please react to this post. Preferably by commenting, I fear that I cannot communicate so well with smoke signals.
Uploading to Amazon S3 using the GAE + Django
The project I’m involved with needed to serve media files to an external data storage, in this case the Amazon S3 storage. I used the following to make this work.
- Google AppEngine
- Django (Appengine helper is recommended)
I created this simple function in the views.py of my app. It basically just sends out the research_id (which is required for some links on the page) and it grabs the research object that I’ll need to read out in the template.
def add_media(request, research_id):
research = Research.get_by_id(int(research_id))
return render_to_response(”research/add_media.html”, RequestContext(request, {’research_id’: research_id, ‘research’: research}))
The following is an excerpt from the template on how to construct the form. If you need help constructing your policy and signature, you can use the following website.
http://www.jfileupload.com/products/js3upload/documentation/policygenerator.html
Add media for: <strong>{{ research.title }}</strong><br />
<form action=”http://YOURBUCKET.s3.amazonaws.com/” method=”post” enctype=”multipart/form-data” id=”mediaForm” onsubmit=’return add_key()’>
<input type=”hidden” id=”key” name=”key” value=”" /><br />
<input type=”hidden” name=”acl” value=”public-read” />
<input type=”hidden” name=”success_action_redirect” value=”YOURREDIRECT” >
<input type=”hidden” name=”AWSAccessKeyId ” value=”YOURACCESSKEY” />
<input type=”hidden” name=”Policy” value=”YOURPOLICY” />
<input type=”hidden” name=”Signature” value=”YOURSIGNATURE” />
File: <input type=”file” name=”file” id=”file” /> <br />
<input type=”submit” name=”submit” value=”Upload” />
</form>
Adjust the form according to your policy wishes. I have no restrictions on the key value, as I serve them dynamically through the javascript function add_key().
<script type=”text/javascript”>
function add_key()
{
var key = document.getElementById(’key’);
var filename = document.getElementById(’file’);
key.value = “{{ research.slug }}/” + filename.value;
}
</script>
So if your research slug would be “testresearch” and your filename is “image.jpg” the output of key would be “testresearch/image.jpg”.
Hope this helps for anyone having any difficulties with GAE and Amazon S3
Export to excel using the Google App Engine and XLWT
I’ve recently starting working on a new webplatform that required the option to export data to an excel document, whilst not taking up any space on the filesystem. Considering that we’re using the google appengine. Now you could use the Amazon S3 storage for this, but as we don’t have any access to an account for that just yet. I chose to take it on as follows:
What you need:
- XLWT: http://pypi.python.org/pypi/xlwt
- Google AppEngine: http://code.google.com/appengine/
- Django: http://www.djangoproject.com
I personally used django set up with the Google App Engine Django Helper.
class ExcelResponse(HttpResponse):
def __init__(self, data, headers=None, force_csv=False, encoding=’utf8′):
research = Research.get_by_id(int(data))
output_name=research.slug
output = StringIO.StringIO()
wbk = xlwt.Workbook(encoding=encoding)
sheet = wbk.add_sheet(research.slug)
sheet.write(0,0, research.title)
wbk.save(output)
mimetype = ‘application/vnd.ms-excel’
file_ext = ‘xls’
output.seek(0)
super(ExcelResponse, self).__init__(content=output.getvalue(),
mimetype=mimetype)
self['Content-Disposition'] = ‘attachment;filename=”%s.%s”‘ % \
(output_name.replace(’”‘, ‘\”‘), file_ext)
We start off by creating a class that will end up returning as a HttpResponse object. Among the *args, data is the one that receives an id from a different function ( see below). We have to typecast data into an int for it to work in the query to research.
output_name will be the filename preceding the extension. Output starts a StringIO object. wbk then creates a new workbook, a sheet is created afterwards with the research slug as its label. We then write the research title to the first row and first cel and save that to the StringIO object. Specify further information for the filetype and then return it to the client.
To put this to use, I’m using a simple request handler that looks like this:
@check_project_owner
def excel_report(request, r_id):
return ExcelResponse(data=r_id)
check_project_owner is a simple decorator that checks if the current logged in user corresponds with the research we’re trying to retrieve. It then returns the HttpResponse object class Excelresponse with the research id as the data.
Windows Messenger Live 2009 build 14
For those of you that cannot login with the latest version of the windows messenger live version. Try the following:
> 1—C:\Program Files\Windows Live\Contacts
> 2—Right click properties of wlcomm.exe
> 3—Click compatibility
> 4— Run on windows 95
> 5— Tick disable visual effects
> 6— Click OK
Source: [Click]
This seemed to fix the problem on my end in any case. Good luck.
The Next Web chapter two
This upcoming Monday I’ll be starting the next semester of my study after a (what seems to be a short) summer vacation. As I have it planned at this moment, I’ll be enrolling in a new Django project. To my knowledge there will be several available, so we’ll see what happens there. Should be good no doubt.
I’ve formatted my laptop and am currently trying out a Windows 7 build, however I’ll be dual-booting it with Ubuntu Linux to get Django set up for the new project. Any interesting developments regarding Django that I come across will be posted here as I have before (kind of!) as demonstrated in the previous post. Now I haven’t really gotten around to get back into the whole ordeal that is Django, but I’m sure it’ll all come back from foggy memories dating back a year.
Next to that I’m currently looking around for a internship that involves webdevelopment / design, Django related would be greatly appreciated. Still unsure whether I want to go abroad for this one or not, it does however seem very appealing for my CV as well as general work experience of course!
Django – Pycha charts
As promised, I’m going to display a simple way to generate a piechart through a form in Django, using Pycha and Cairo. You’ll need to get the libraries for both naturally (Google is your friend). Do note that I’m showing it to you in the simplest of ways.
Starting off right away with the forms.py:
We’re creating a small form with 8 input values. 4 Labels for the corrosponding 4 values, as shown below.
class PieChartForm(forms.Form):
val_1_label = forms.CharField(max_length=45)
val_1 = forms.IntegerField()val_2_label = forms.CharField(max_length=45)
val_2 = forms.IntegerField()val_3_label = forms.CharField(max_length=45)
val_3 = forms.IntegerField()val_4_label = forms.CharField(max_length=45)
val_4 = forms.IntegerField()
That is basically all we need as far as the forms go. Moving on to the views.py, we’ll start off with some essential imports.
import cairo
import pycha.pie
import pycha.bar
from pycha.chart import Option
Moving on to the function itself.
def piechart(request):
if request.method == ‘POST’:
form = PieChartForm(request.POST)
if form.is_valid():
This bit checks whether there is POST data availablem if so it requests the data for the form. Then it checks whether the form data is actually valid. Following is a lengthy-ish bit of code to sort out all the data.
graph_lable1 = request.POST.get(’val_1_label’).encode(’latin-1′)
graph_lable2 = request.POST.get(’val_2_label’).encode(’latin-1′)
graph_lable3 = request.POST.get(’val_3_label’).encode(’latin-1′)
graph_lable4 = request.POST.get(’val_4_label’).encode(’latin-1′)graph_val1 = int(request.POST.get(’val_1′))
graph_val2 = int(request.POST.get(’val_2′))
graph_val3 = int(request.POST.get(’val_3′))
graph_val4 = int(request.POST.get(’val_4′))
The above section places the post data into variables and casts them into strings and integers. As the generator cannot process unicode results. We move on by defining the actual canvas to draw on, including the insertion of data.
width, height = (500, 400)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
dataSet = (
(graph_lable1, ((0, graph_val1), (0, 0))),
(graph_lable2, ((0, graph_val2), (0, 0))),
(graph_lable3, ((0, graph_val3), (0, 0))),
(graph_lable4, ((0, graph_val4), (0, 0))),
)
In this case it’ll be a 500 x 400 canvas. Also, the additional zeroes are indeed required if you wish for the generator to actually generate anything other than an error. Next up we can set some options for the generator.
options = {
‘legend’: {’hide’: False},
‘background’: {’color’: ‘#fff’},
‘colorScheme’: ‘blue’,
}
The options within do exactly what they say, so I won’t be going into that. We continue by actually saving the PNG file.
filename = ‘/home/user/png-gen/png-file.png’
chart = pycha.pie.PieChart(surface, options)
chart.addDataset(dataSet)
chart.render()
surface.write_to_png(filename)
Naturally, you can do a lot of things with the filename. I created the function for a website that allows the creation of this within projectgroups. So we needed a way to allow for several files to be generated for a group instead of having them overwrite eachother continuously. This is the variable I used:
current_time = str(datetime.datetime.now().strftime(’%Y-%m-%d-%H:%M:%S’))
filename = settings.MEDIA_ROOT + ‘/project_files/’ + str(project_id) + ‘/graphs/piechart-’ + current_time + ‘.png’
If you’ve completed all the above steps, you’ll need to return the function to something. You could use a render_to_response to write the generated image back to a template. Like so:
return render_to_response(”app/media_render.html”, locals(), context_instance = RequestContext(request))
You can add the following for the form validation and for when there is no POST data available:
else:
# If the form does not return valid data, provide an alert message and redirect link to the previous page
return HttpResponse(”Error message here”)
else:
# If there is no POST data, generate the form
form = PieChartForm()
return render_to_response(”businessplan/piechart.html”, {’form’: form}, context_instance = RequestContext(request))
Good luck!
P.S. Do mind the indenting, that’s something WordPress does not do so well without the code plugin that I haven’t gotten around to installing just yet.
Things to come..
A couple of things that I want to re-add in the near future are as follows:
Overview of my presentation on Web Usability
I did a presentation some time ago about Web Usability, I’ll share it in text form in the near future.
Pycha Charts
Another feature I’ve developed for an ongoing project that involves using a form to generate a .PNG of several charts.
(PieChart, Vertical/Horizontal bar charts for example)
Over the past few weeks I’ve familiarized myself with the Django framework for Python. As far as anyone can within just a couple of weeks. The main issue I’m having with Django momentarily is, that a lot of things that we are trying to accomplish get’s us confronted with errors that are quite simply undocumentated. I’ve even had to get an answer through a Chinese website once, go figure.
I’m guessing however that if Django does turn out to be as popular as some people seem to rave about it, one would hope that they brush up on that particular area (documentation). Not that there isn’t any available, there is a lot available momentarily. However if you’re working for a specific outcome that deviates slightly from generic projects… You may find yourself learning a few vulgar words you thought never existed.
Guess you’ll learn something one way or the other then!
A new beginning
After some difficulties with my hosting, I found out that not all my data was backed up. So I pretty much lost all the data I had present on the blog. I’ll be writing up a couple of posts in the near future as my project with Django continues.
Happy new year as well of course.