In a subsequent job, I needed to learn Python, and I found the transition from Ruby to be pretty easy. There are a few Ruby-isms I missed but for the most part I was fine with Python. I still used a variant on the old Rails project, but decided to explore Django, since it's Python as well, and it's always better to simplify, if you can. What I didn't expect, though, was just how much simpler Django was going to be than Rails.
My projects, as I said, are very simple. Regression test results (and other data, such as apache benchmarks and server performance monitoring data) are stored in simply MySQL databases. I want access to these results through a browser. Most of the results are presented in HTML tables. Others are displayed in Google Charts.
in Rails I needed separate files for each database table's corresponding controllers, models and and views. I also touched the databse.yml file, the routes.rb and migrate files. I don't really have anything in the app/helpers or lib or log or public or script or test or tmp or vendor directories, yet there they are! In Rails, the views directories for each table contain index, new, show, edit and delete html files. In sum, there are more than 40 files to edit and maintain in my bare-bones Rails project.
In the Django version, there are the main 3 files (manage,py, settings.py and urls.py), and then one file for all models (models.py) and one file for all views (views.py). I have html template files for each table, so that's another 5 - for a total of 10 files. There are no unused folders, no other clutter.
And that's not all. In Rails, I had to write MySQL scripts to extract the data and Ruby code to pass the results up through the controller to the view, stuff like this:
def self.find_history date = (Date.today-30).to_s stmt = "select * from (select server, date from ads f1 group by server order by date desc) f1 left join ads f2 on f1.server=f2.server and f2.date > '#{date}'" result = find_by_sql(stmt) @server = Array.new @mean1 = Array.new @mean2 = Array.new @mean3 = Array.new @date = Array.new result.each do | a | @server << a.server @mean1 << a.mean1 @mean2 << a.mean2 @mean3 << a.mean3 p = a.date.to_s.split(" ") @date << p[0] end return result endIn Django, no. I just define the db in the models file:
class Benchmarks(models.Model): server = models.CharField(max_length=128) users = models.CharField(max_length=32) mean1 = models.CharField(max_length=32) mean2 = models.CharField(max_length=32) mean3 = models.CharField(max_length=32) date = models.DateTimeField()
And in the views file I use a built-in method to get the data from MySQL, then use a 'context' to pass it along to a 'template' file which will be rendered by the browser
def benchmark_index(request): all_entries = Regression.objects.all() t = loader.get_template('benchmark/index.html') c = Context({ 'all_entries': all_entries, }) return HttpResponse(t.render(c))The template is similar in look-and-feel to embedded Ruby. You put Python code in between {% and %} markers, and the rest is html:
table here:
tr
th>Server
th>Users
th>Mean Response Time 1
th>Mean Response Time 2
th>Mean Response Time 3
/tr
{% if all_entries %}
{% for a in all_entries %}
tr>
td>{{ a.server }}
td>{{ a.users }}
td>{{ a.mean1 }}
td>{{ a.mean2 }}
td>{{ a.mean3 }}
td>{{ a.date }}
{% endfor %}
{% endif %}
/tr>
Notice that 'all_entries' - the variable used in the template, was explicitly defined in the views file and passed into the context. Also, the urls used by Django are explicitly defined, formed by regular expressions, and stored all together in a file called urls.py:
urlpatterns = patterns('', # Examples: (r'^benchmarks/$', 'regression.views.benchmark_index'), )
It makes it clear that the url is ROOT/benchmarks, and when you go there, you invoke the method 'benchmark_index' in the views.py file in the 'regression' application. It's all quite explicit and easy to track.
This is most of the project in a nutshell. A simple db with values easily retrieved and displayed in an HTML table in a browser.
bonus coverage: The google charts aspect was also straightforward. 1) Install the Python module: sudo easy_install -U GChartWrapper 2) embed some google chart code in your template file 3) create and pass the data to the chart from the views.py file
Building on the example above, add to the benchmark_index and template file:
def benchmark_index(request): all_entries = Benchmarks.objects.all() data = [] max_val = 0 for a in all_entries: if a.mean3 > max_val: max_val = a.mean3 data.append(a.mean3) #print max_val mid_val = float(max_val) / 2 t = loader.get_template('benchmark/index.html') c = Context({ 'all_entries': all_entries, 'data': data, 'max_val': max_val, 'mid_val': mid_val, }) return HttpResponse(t.render(c))
// in the template, below the sample code above
{% load charts %}
{% chart Line data %}
{% title 'Max Mean Response Times' 0000FF 36 %}
{% color 3072F3 %}
{% line 3 2 0 %}
{% size 600 200 %}
{% axes type xy %}
{% scale 0 max_val %}
{% marker 's' 'blue' 0 -1,5 %}%}
{% legend 'Mean Response Times' %}
{% axes range 1 0,max_val %}
{% axes label 0 %}
{% axes label 1 0 mid_val max_val %}
{% img alt=DataScaling height=200 id=img title=DataScaling %}
{% endchart %}
The result:
Nothing fancy, but there you have it. Why complicate your life? Simplify with Django and Python.
No comments:
Post a Comment