About Django Dash
Django Dash is an online, weekend Django hackathon. You get 48 hours to develop a Django app of some sort, from scratch.
Apart from being a lot of fun, its a great way to squeeze in a bunch of learning over a short period of time. Kausik and I set out to build a badge generation application.
(View the site here - Make My Badge)
The idea
A lot of people probably know about the badge generation python script. This is a script that takes a list of people, a badge template and generates badges for all the attendees. The badges can be printed out and laminated beforehand for attendees to pick up at the event registration.
The badge design itself is based on a simple principle (surprisingly violated by a huge number of events!) - keep the name large and easy to read from across the hall. We wanted to avoid badges where the name of the event is prominent but the name of the person is tiny. I'm also not a fan of handwritten badges. Not only do they look ugly, but the scribbling is rarely readable.
We also wanted to auto-scale the font size based on the length of the name, and to split long names into two lines so that we could use larger font sizes. These badges have been used in a number of events in Chennai, and have always been popular, with some people even preserving them as souvenirs. (See the badge in use)
One of the problems with the script is that you need some technical knowledge to generate the badge. This made it complicated for a people to generate badges for an event. It also made it difficult to generate and print badges on the fly at the registration desk for on the spot registrants.
We decided to build a web app in 48 hours to do everything that the badge generator did, but as a Django site.
Something that we wanted to do (apart from developing the site of course) was to get up to date on the current cutting edge technology in the Python/Django space. Sure we use a lot of cutting edge tools for ToolsForAgile.com but that application is now almost 3 years old. Although we do keep updating it, its a big application and updating platforms and infrastructure can take time. Plus we wanted to do a quick spike of some of the technologies so that we could take the learning back to our product. Django Dash was the perfect opportunity for that.
Here are some of the things we learned
Django deployment scenarios
When we first developed our product, the only option for python and django deployments was to use Apache with mod_python. Then the WSGI standard was finalised and mod_wsgi came along. mod_python is now officially end-of-line with no more support available for it.
Today one popular deployment configuration is to use an nginx frontend server to serve static files, with a reverse proxy to an Apache + mod_wsgi configuration to serve dynamic files.
Apart from Apache, a lot of other backend servers are becoming popular, most notably gunicorn.
Django hosting
There are now a gazillion hosting providers for Django. When we started out with ToolsForAgile.com the only option was to roll your own setup on a VPS or dedicated server. You still want to do that for complex deployment setups, but there are now any number of django specific hosts for the common scenarios - ep.io, gondor.io, Stable, Dotcloud, AppHosted, DjangoZoom. Ken Cochrane has an excellent series of blog posts with a comparison of django hosting providers.
All these services allow you to simply deploy, while they handle setting up the deployment stack, load balancing and auto scaling for you.
And of course, for the simpler use cases, there is always good old Webfaction. I've hosted various sites with them for four years, with not a single problem so far.
ep.io
ep.io and gondor.io were sponsoring Django Dash, so apart from setting up a custom stack on a Linode VPS, participants also had the choice of deploying on one of these services. We decided to try out ep.io for our submission.
Overall, I must say that I really liked ep.io. It was a bit complicated to get my head around first. It took a while to get file uploads, static files and celery set up. That was more to do with the fact that we were using ep.io for the first time. Once setup, deployment was a breeze. All we had to do was to upload the project using their command line client and ep.io would automatically provision the app with all the required services. They also have an interface where you can push your project directly via git or mercurial.
I should note here that the ep.io client only works in linux as it requires ssh to execute remote commands. Since we were on windows, it took us a fair while to hack up the client and hook it up to do its work through Putty instead.
pip
This is the first time we exclusively used pip along with a requirements.txt file to sync up the python dependencies of all the local dev environment as well as the remote server setup. It worked really well. pip rocks!
Celery
Celery is a distributed task queue. It's amazing how popular it has become in such a short span of time. For our submission, we decided to try out celery to generate the badge images asynchronously through the tasks queue.
Celery can work on top of a number of transports. Popular configurations are to use it over an AMQP broker like RabbitMQ or over Redis. We used it over RabbitMQ (which in turn requires Erlang), whereas ep.io supports celery over Redis. The nice thing is that we just had to tell ep.io that we wanted to use celery and it would set everything up, including launching the celery daemon, configuring it to use redis and what not.
On our side, we used django-celery, a Django integration of celery. With djcelery you can create a tasks.py file in your app with a bunch of task definitions which you can call asynchronously through a view.
After some initial setup hiccups, it worked like a charm, allowing us to push out the badge image generation out to the workers. When badge generation was done, it would trigger another task to zip up all the images and allow the user to download a single zip with all the badges. Everything happening through Celery. It was pretty exciting to see the whole flow in action.
Django 1.3
We used Django 1.3 for this submission. Our product is built on a version of django that is somewhere between 1.1 and 1.2.
We got a chance to play with some of the new stuff in 1.3. We got a chance to try out class based generic views, the new logging setup, TemplateResponse, some improvements to the admin, and a bunch of other stuff.
The admin interface itself is a huge section to explore. We briefly thought about doing the whole site through a custom admin interface, but we were running out of time so we shelved the idea for the time being.
Django 1.3 also has a completely new way of dealing with static files. The old django-staticfiles app has been added as a contrib package and is now the official way to handle static files. The old way had a single static directory with all the static files in it. You now have to put your static files either under an app folder, or in a global static dir. You then call the collectstatic management command to pull in all the static files into a directory that the frontend server will serve.
Similarly, there seems to have been a change in the way uploaded files are handled. Previously they used to go under the static folder. They now get a folder of their own.
What got done in 48 hours
We eventually ran out of time on all the features that we wanted. Thats not surprising, with the amount of new stuff we were using for the first time. It took almost one and a half days to setup and get comfortable with ep.io, celery, django-celery and all the changes in Django 1.3, and getting them to work properly on the local dev environment and online on ep.io.
However, since we built the whole app incrementally, we managed to get the important features in. If you go to Make My Badge you'll be able to login, generate and download a sample set of badges. You can create events, though you need to go to the admin interface to add people to the event.
What is left to do?
We ran out of time before we could integrate django-registration for new users to register. We've created a sample user through the admin interface for now. We also wanted to be able to upload a list of event attendees through a CSV upload form, but couldn't put that in. As a workaround, you need to add people through the admin interface.
Apart from those two main features, there were lots of UI design work that we wanted to do which we couldn't finish.
Where are we going from here?
Once the event judging is over, we have a bunch of enhancements to add. The CSV upload feature, for example, got done about 2 minutes past the deadline. We want to put that in. Integration with django-registration is also ready on the development environment.
We want to eventually add integration with a payment system. Charge Rs.1 per badge generated or something like that.
Overall Impressions
Django Dash was awesome fun. Although we couldn't complete everything we sure did learn a lot of new things that we can take back into other projects. And now that we know the tech, I'm pretty certain we can have a similar app complete in 48hrs.
I was just going through some of the teams, and here are some submissions that I found. Remember, all these were done by scratch in 48 hours! - Drawn by, Family Feed, ProposalMatic, FutureFI, Goal Rally, Django Lint, ConsoliTweet, Courtside, Linky, Git Awesome, Stardust, Set With Me, Libman, Show Offfr, SmartLinky, Staste, Django Docs, Code War, Grepo, Codr Space, My Img, Gearoscope
Flickr Badge
Showing posts with label django. Show all posts
Showing posts with label django. Show all posts
Monday, August 01, 2011
Wednesday, October 22, 2008
Must watch videos from DjangoCon
I was recently going through some of the videos from DjangoCon. Two must watch videos are Cal Henderson's talk titled "Why I Hate Django" and Mark Ramm's talk "A Turbogears guy on what Django should learn from Zope". Both Cal and Mark bring in interesting outside perspectives that I hadn't really considered before. Both talks run around an hour each and are well worth watching if you have the time.
Friday, May 30, 2008
Screencast: Using Amazon S3 with Django
Many thanks to Balaji and CSS for organising the second Amazon Web Services meet in Chennai and to Jinesh for being able to make it. (Also check out my live blog of the event on twitter, starting here)
As a part of this meet, I had prepared a demo showing how to build a simple gallery application using Django and Amazon's S3 service. I've recorded it as a screencast and uploaded it on ShowMeDo. It's really simple to use S3 with Django, so take a look.
This screencast uses the Boto python library for accessing AWS.
As a part of this meet, I had prepared a demo showing how to build a simple gallery application using Django and Amazon's S3 service. I've recorded it as a screencast and uploaded it on ShowMeDo. It's really simple to use S3 with Django, so take a look.
This screencast uses the Boto python library for accessing AWS.
Get the Flash Player to see this movie.
This video originally comes from here at ShowMeDo from the Python category.
Labels:
"web services",
amazon,
aws,
django,
programming,
python,
screencast
Wednesday, April 09, 2008
Google announces App Engine, takes on Amazon?
So Google is getting into scalable web infrastructure with the announcement of Google App Engine, apparently taking on Amazon's EC2 and S3 services. Having taken a deeper view however, it seems like they are addressing completely different spaces.
EC2 and S3 offer a whole lot of flexibility. They are independent of each other for a start, which means you can use S3 alone, or EC2 alone, or in combination with Amazon's Simple Queue Service. Secondly, with EC2 you get complete control over the image. You can put any programs in it and you can configure them however you want. You can even run anything on the instance from serving pages to performing computations.
Google's offering is completely different. You can only run web apps. It has to be in Python. You have to use their APIs for accessing data or fetching URLs. No sockets, no subprocesses, no threading, no filesystem access. So there are a lot of limitations.
BUT, what you get in exchange is extreme simplicity. App Engine is perfect for web app that needs to store some stuff in a database and interact with the user via a web server - and that's most of the apps out there. You've even got an SDK to develop offline and then sync it online.
Another bonus for Django developers: The APIs seem to be heavily influenced by Django. What this means is that if you are a Django developer, it should be relatively straightforward to deploy your applications onto App Engine. In fact, there is even some official documentation for doing just that.
If you design your application well, it shouldn't be too complex to take a Django app and port it to use the App Engine API, and vice-versa, take an App Engine app and move it to Django on another web host. That way you do not have platform dependence to Google and you can still move to another web host in the future.
EC2 and S3 offer a whole lot of flexibility. They are independent of each other for a start, which means you can use S3 alone, or EC2 alone, or in combination with Amazon's Simple Queue Service. Secondly, with EC2 you get complete control over the image. You can put any programs in it and you can configure them however you want. You can even run anything on the instance from serving pages to performing computations.
Google's offering is completely different. You can only run web apps. It has to be in Python. You have to use their APIs for accessing data or fetching URLs. No sockets, no subprocesses, no threading, no filesystem access. So there are a lot of limitations.
BUT, what you get in exchange is extreme simplicity. App Engine is perfect for web app that needs to store some stuff in a database and interact with the user via a web server - and that's most of the apps out there. You've even got an SDK to develop offline and then sync it online.
Another bonus for Django developers: The APIs seem to be heavily influenced by Django. What this means is that if you are a Django developer, it should be relatively straightforward to deploy your applications onto App Engine. In fact, there is even some official documentation for doing just that.
If you design your application well, it shouldn't be too complex to take a Django app and port it to use the App Engine API, and vice-versa, take an App Engine app and move it to Django on another web host. That way you do not have platform dependence to Google and you can still move to another web host in the future.
Tuesday, March 25, 2008
Why doesn't Django find my unit tests?
I ran into a Django gotcha today. I had an app for which it was simply not running the unit tests. The tests were there in the correct location. Django was correctly running the tests for all the other apps. Why was it not running the tests for this one? I checked settings.py to see if the app was in
I got my answer after some digging around in the Django source. It appears that you must have
Once I had that figured out, the solution was simple - recreate the empty
This whole thing is really unintuitive though. Who would have thought that removing an empty file would cause the tests to stop running? There doesn't seem to be any connection between them at all.
In a broader sense, any piece of code that uses
This is exactly the kind of unintuitive "magic" that we Pythonistas hate :) Explicit is better than implicit etc.
What I don't understand is that the list of installed apps *IS* explicit. It's sitting there called
INSTALLED_APPS. It was. It worked fine through the browser, and the test code looked good. What was worse, it was working when I last ran it before the weekend. Why did it suddenly stop running?I got my answer after some digging around in the Django source. It appears that you must have
models.py in the app for tests to run. It so happened that this app has no models, only some views that do some calculations. Since models.py was empty, I had deleted it and didn't think too much about it. Whoops! The tests stopped running.Once I had that figured out, the solution was simple - recreate the empty
models.py, and the tests started running again.This whole thing is really unintuitive though. Who would have thought that removing an empty file would cause the tests to stop running? There doesn't seem to be any connection between them at all.
In a broader sense, any piece of code that uses
django.db.models.get_apps to get a list of installed apps is likely to run into this problem. Don't be surprised if you remove an empty models.py and then something breaks and you are left scratching your head as to what exactly happened.This is exactly the kind of unintuitive "magic" that we Pythonistas hate :) Explicit is better than implicit etc.
What I don't understand is that the list of installed apps *IS* explicit. It's sitting there called
INSTALLED_APPS in settings.py. Why does Django go about hunting through the models when it could just read this value? Any clues?
Saturday, March 22, 2008
Has Django reached the tipping point?
Antonio Cangiano thinks so. The numbers used to come to this conclusion are not exactly scientific, but there's no doubt that Django is getting bigger (and better) everyday.
Monday, February 11, 2008
Screencast on many to many relationships between Django models
My third introductory screencast for Django. It follows on from the first screencast and the second one.
Get the Flash Player to see this movie.
This video originally comes from here at ShowMeDo from the Python category.
Tuesday, October 30, 2007
Looking for Django developers?
Check out Djangogigs.com. Djangogigs is a new website for matching Django developers with Django jobs. If you are looking out for some Django work, add yourself to the site.
Tuesday, October 23, 2007
Django Screencasts
A few people have been asking for introductory Python + Django material, so I thought I'd just link up to the two intro screencasts that I did for Django.
Learn Django: Create a Wiki in 20 minutes
This is a beginners screencast that assumes no previous knowledge of Django. We illustrate the basics of creating a web app in Django by developing a simple wiki application.
Learn Django: Extending the wiki with wikiwords and search
Following on where the first screencast left off, this screencast introduces some more django features such as template inheritance, filters and newforms library.
Learn Django: Create a Wiki in 20 minutes
This is a beginners screencast that assumes no previous knowledge of Django. We illustrate the basics of creating a web app in Django by developing a simple wiki application.
Learn Django: Extending the wiki with wikiwords and search
Following on where the first screencast left off, this screencast introduces some more django features such as template inheritance, filters and newforms library.
Tuesday, September 11, 2007
Django screencast: Template inheritance, filters and newforms
Following up on my first Django screencast, I've put up the second screencast in the Learn Django series. Like the first one, its hosted on showmedo.com and you can view the screencast here.
The second screencast extends the wiki application we built in the first part by adding a menu, support for auto-linking of wikiwords and a feature to search through the database. In the process, you'll learn about some cool Django features such as template inheritance, custom filter libraries and Django newforms. Django newforms in particular is a very cool form handling library that can really cut down on boilerplate form generation and validation code.
Interested? Check out the screencast.
The second screencast extends the wiki application we built in the first part by adding a menu, support for auto-linking of wikiwords and a feature to search through the database. In the process, you'll learn about some cool Django features such as template inheritance, custom filter libraries and Django newforms. Django newforms in particular is a very cool form handling library that can really cut down on boilerplate form generation and validation code.
Interested? Check out the screencast.
Wednesday, July 25, 2007
My first ShowMeDo video
ShowMeDo is a website started by Ian Ozsvald and Kyran Dale. The idea is to have a collection of technical screencasts on a variety of subjects. I just got my first screencast hosted at ShowMeDo. It is a re-recorded version of my earlier screencast on doing a wiki in Django, this time with a voice over. Have a look here.
Saturday, July 14, 2007
Django Code Coverage Followup
teenage mutant ninja hero coders builds on my post on code coverage with django and shows how you can get the same effect by creating an alternate test runner. This way, you can get code coverage without having to muck around in the django source.
Pretty cool. I'll have to try this out.
Link
Pretty cool. I'll have to try this out.
Link
Tuesday, May 29, 2007
Django code coverage for doctests
As a followup to my post on code coverage for your Django code, Eddy Mulyono shows how you can get code coverage working with Django when you use doctest for unit testing. Check it out here.
Sunday, April 22, 2007
Code coverage for your Django code
One of the things that I like about Django is that it allows you to run unit tests on the code with relative ease. So I have a bunch of unit tests now, and I was looking to expand it. For that I first needed to know which parts of the code had good coverage and which parts had no coverage. I needed to integrate code coverage with the unit testing framework. In the end, it involved modifying a few files. This is what I did:
- First, I downloaded Ned Batchelder's coverage.py module.
- Next, get this script to colorize the coverage output. I saved it as coverage_color.py
- Put both files somewhere on the python path. I put it at Python24\Lib\site-packages
- Now we need to modify the django unit test runner to include coverage. Head over to your django\test directory and edit the simple.py file
- At the top, add the following line:
import os, coverage, coverage_color
- Scroll down to the run_tests function. You will see a line like this:
unittest.TextTestRunner(verbosity=verbosity).run(suite)
destroy_test_db(old_name, verbosity) - Modify it to read like this:
coverage.start()
unittest.TextTestRunner(verbosity=verbosity).run(suite)
coverage.stop()
if not os.path.exists(settings.COVERAGE_DIR):
os.makedirs(settings.COVERAGE_DIR)
for module_string in settings.COVERAGE_MODULES:
module = __import__(module_string, globals(), locals(), [""])
f,s,m,mf = coverage.analysis(module)
fp = file(os.path.join(settings.COVERAGE_DIR, module_string + ".html"), "wb")
coverage_color.colorize_file(f, outstream=fp, not_covered=mf)
fp.close()
coverage.erase()
destroy_test_db(old_name, verbosity) - What that does is to record the coverage when running the tests. It then creates a directory for putting the HTML output, creates the colorized version of the source and dumps it into the output directory. At the end of everything, it cleans up the coverage data
- We now need to configure the COVERAGE_DIR and COVERAGE_MODULES settings. Open your Django settings.py file and add the following lines:
COVERAGE_DIR = "scripts/build/coverage" # Where the HTML output should go
COVERAGE_MODULES = ["apps.catalyst.views", "apps.catalyst.models"] # The modules that you want colorized - Save and run your Django unit tests. After running, you will have a html file for each module in the specified directory with the colorized coverage output
Wednesday, February 28, 2007
Django screencast: Create a wiki in 15 minutes
I've uploaded a screencast on how to write a wiki in 15 mins with Django. Its available on the Silver Stripe Blog here.
Tuesday, December 19, 2006
Using python decorators to implement guards
One cool technique that I learnt while going through the Django code was using python decorators to implement guards.
What are guards?
Take a look at this bit of pseudo-code
The solution is to refactor the code to use guards.
Python decorators
Python has a decorator feature that allows you to modify the function that it is applied to. Here is an example:
Implementing guards using decorators
We can now see how guards can be implemented using decorators. Let me take a real example that I've encountered — my admin page. My tool has an admin page. In order to access this page, you must be logged in, and you must be an admin. If you are not logged in, you need to be redirected to the login page. If you are not an admin, an error message should be displayed. This is how the code would normally have looked
See how neatly the guards are separated from the core logic. The admin function contains only the core logic, while the list of guards is neatly arranged as decorators. This method also has another advantage — it is easy to apply the same guards to other functions. Take a look at this
This post is a part of the selected archive.
What are guards?
Take a look at this bit of pseudo-code
if condition1:This is a common pattern where you do something provided condition1 and condition2 are false. The problem with this code is that it is difficult to seperate out the core logic of the function contained in {do_something} and the error handling code in the rest of the function. Another disadvantage is that the condition is at the top of the function, while the failure action is at the bottom. This makes it difficult to correlate the condition with the failure action.
if condition2:
{do_something}
else:
return error2
else:
return error1
The solution is to refactor the code to use guards.
if not condition1:Guards are the conditions at the top of the function. They act like security guards — If the condition passes you go through, otherwise you leave the function. It is now a lot easier to see the conditions and the failure actions, and you can easily identify the code logic block by just skipping past the guards.
return error1
if not contidion2:
return error2
{do_something}
Python decorators
Python has a decorator feature that allows you to modify the function that it is applied to. Here is an example:
def decorate(fn):What we have is a function myfunction that prints the string "in function". To this, we apply the decorator 'decorate' (denoted by the @ symbol). decorate is itself a function that takes one function as a parameter and returns another function. In this case, it takes fn as a parameter and returns _decorate. Everytime myfunction is called, it will actually call the returned function, in this case _decorate. _decorate prints "before calling", then it calls the original function, then prints "after calling". Here is the output
def _decorate():
print "before calling"
fn()
print "after calling"
return _decorate
@decorate
def myfunction():
print "in function"
>>> myfunction()
before calling
in function
after calling
Implementing guards using decorators
We can now see how guards can be implemented using decorators. Let me take a real example that I've encountered — my admin page. My tool has an admin page. In order to access this page, you must be logged in, and you must be an admin. If you are not logged in, you need to be redirected to the login page. If you are not an admin, an error message should be displayed. This is how the code would normally have looked
# check for loginHere is a version using decorators
try:
user = request.session["user"]
except KeyError:
# redirect user to login page
# check for admin
if not user.isAdmin():
# display error page
# show admin page
...
# login decorator checks whether the user is logged inThis is how it works. We first have the admin function. All it does is implement the admin code. We decorate it with the admin_required and login_required decorators. When the admin function is called, it first enters the login_required decorator function which checks for login. If the user is not logged in, it redirects to the login page, else it calls the function. The function passed to login_required is the admin_required decorated function. So if login passes, it calls the admin_required decorator, checks for admin. If the user is not an admin, it displays an error message, else calls the function, which in this case is the original admin function.
def login_required(fn):
def _check(request, *args, **kwargs):
try:
user = request.session["user"]
except KeyError:
# redirect to login page
# user is logged in, call the function
return fn(args, kwargs)
return _check
# admin decorator checks whether the user is an admin
def admin_required(fn):
def _check(request, *args, **kwargs):
user = request.session["user"]
if not user.isAdmin():
# return the error page
# user is admin, call the function
return fn(args, kwargs)
return _check
@login_required
@admin_required
def admin(request):
# show admin page
...
See how neatly the guards are separated from the core logic. The admin function contains only the core logic, while the list of guards is neatly arranged as decorators. This method also has another advantage — it is easy to apply the same guards to other functions. Take a look at this
# no decoratorsNow each function only implements the core logic, while all the guard logic is taken care of by the decorators. It is easy to see the core logic and easy to see the guard conditions applied for the function. If I want some other function to have a guard, I can just add a decorator to it without touching the core logic. Best of all, the code is self descriptive and very easy to read.
def login(request):
...
@login_required
@admin_required
def admin(request):
...
@login_required
def dashboard(request):
...
@login_required
@project_permission_required
def view_project(request, project):
...
This post is a part of the selected archive.
Thursday, December 14, 2006
Rapid Web App Development — My experiences while developing Catalyst
My talk at the barcamp was titled "Rapid Web App Development — My experiences while developing Catalyst". Catayst is the name of my project management tool. The presentation was created using a modified version of Eric Meyer's S5 presentation tool. The template allows you to create the presentation content in XHTML and style it using CSS. It's really awesome, and I feel a lot more comfortable with it than Powerpoint or OpenOffice. However, there is no place to upload it. Another problem of putting the slides online is that it lacks the voice over and discussion that actually took place. Since the slides by themselves are pretty meaningless, I've added some commentary below.
The goal: Write a web application with one person, one month of work to get to version one. That's what I'm trying to do with Catalyst. I've spent about 80 hours working part time on Catalyst. At that time, it was only a hobby project for me to learn Django, and AJAX. I've worked about 100 hours on it full time since I returned to India. I'm hoping to get to beta before the end of the year.
Catalyst is a project management tool for small, agile and distributed teams. If you have ever been frustrated with the lack of visibility into what everyone else is doing in the project, especially with multiple offices, then Catalyst is for you. But this presentation is not about Catalyst. It is about what I have learnt while attempting to develop an application in a month.
There are six points that I want to discuss, split into two areas. The first area is the philosophy, and the first point is that constraints are good.
Second is the 'less is more' philosophy. There are two angles to this. The first is that the fewer requirements you have, the less you have to design, code and test. In that sense, it obviously help you finish faster and get the product out. The other way of looking at it is simplicity. If you look at Catalyst, it does not have an integrated bug tracking system like many project management systems. Why? By eliminating bug tracking from the list of features, I retain the focus on project management. Not only does it simplify Catalyst, but the users can continue to use their favourite bug tracking tool. In my opinion, this combination is actually worth more than having integrated bug tracking within Catalyst.
The second area I want to focus on is execution. This is the actual development part. How do you speed it up? My favourite is the combination of expressive languages and powerful frameworks. Catalyst is written in python and django. Here is an example: In the project dashboard screen, we need to get all the tasks that are a part of the interation that is currently in progress. The python code to do this is just six lines, with no SQL to be written!
The fifth point is to do smart testing.
Finally, use libraries! The less code you have to write, the easier it is. Catalyst uses Dojo and Mochikit on the client side. Dojo has a bunch of widgets that really ease development, while Mochikit has a really cool DOM creation API. Catalyst uses both. PIL is used on the server side to generate charts. Apart from this, a lot of repeated code has been refactored into libraries. This is general good practise of course, but its often not done. See how the constraints force you to develop better?
To summarise, here are the six points again
The goal: Write a web application with one person, one month of work to get to version one. That's what I'm trying to do with Catalyst. I've spent about 80 hours working part time on Catalyst. At that time, it was only a hobby project for me to learn Django, and AJAX. I've worked about 100 hours on it full time since I returned to India. I'm hoping to get to beta before the end of the year.
Catalyst is a project management tool for small, agile and distributed teams. If you have ever been frustrated with the lack of visibility into what everyone else is doing in the project, especially with multiple offices, then Catalyst is for you. But this presentation is not about Catalyst. It is about what I have learnt while attempting to develop an application in a month.
There are six points that I want to discuss, split into two areas. The first area is the philosophy, and the first point is that constraints are good.
Most of us think of constraints as bad, something that limits our freedom, but constraints can be good. Take the example of the one month limit, an arbitrary constraint. Why develop version 1 in a month? Why not six months or a year? I could have chosen a year and done a lot more features, but the one month constraint forces me to select the most important features and implement them first. In this case, the constraint helps me to focus on what is essential. Constraints can also drive innovation and spur creativity.The more constraints one imposes, the more one frees one's self. And the arbitrariness of the constraint serves only to obtain precision of execution — Igor Stravinsky
Second is the 'less is more' philosophy. There are two angles to this. The first is that the fewer requirements you have, the less you have to design, code and test. In that sense, it obviously help you finish faster and get the product out. The other way of looking at it is simplicity. If you look at Catalyst, it does not have an integrated bug tracking system like many project management systems. Why? By eliminating bug tracking from the list of features, I retain the focus on project management. Not only does it simplify Catalyst, but the users can continue to use their favourite bug tracking tool. In my opinion, this combination is actually worth more than having integrated bug tracking within Catalyst.
The second area I want to focus on is execution. This is the actual development part. How do you speed it up? My favourite is the combination of expressive languages and powerful frameworks. Catalyst is written in python and django. Here is an example: In the project dashboard screen, we need to get all the tasks that are a part of the interation that is currently in progress. The python code to do this is just six lines, with no SQL to be written!
The fifth point is to do smart testing.
You'll never write error free code and since there is only one person, you have to rely on automated tests. Javascript code is unit tested using jsUnit. I am looking to start using the Django extensions to python's unittest module for testing the server side code. Another tool I want to learn is Selenium for automated system tests. Of course manual tests have their place too. I am using catalyst to manage my development work, so that kind of dogfooding helps in areas like usability and finding bugs via basic exploratory testing.There are two ways to write error-free programs; only the third works. — Alan Perlis
Finally, use libraries! The less code you have to write, the easier it is. Catalyst uses Dojo and Mochikit on the client side. Dojo has a bunch of widgets that really ease development, while Mochikit has a really cool DOM creation API. Catalyst uses both. PIL is used on the server side to generate charts. Apart from this, a lot of repeated code has been refactored into libraries. This is general good practise of course, but its often not done. See how the constraints force you to develop better?
To summarise, here are the six points again
- Constraints are good
- Less is more
- Expressive languages
- Powerful frameworks
- Smart testing
- Libraries
Sunday, September 24, 2006
Export django database to an xml file
Here is a simple python script to export your django database to an XML file. I haven't tested it out very thoroughly. It seems to work for the fields that I have in my model - CharField, TextField, DateField, IntegerField, PositiveIntegerField and ForeignKey. If you find any bugs, add a comment to this post.
This post is a part of the selected archive.
# setup the environmentNote to self: Find a better way to colorize the source code
import os, sys
sys.path.append(os.pardir)
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
class XMLWriter:
"""Helper class to write out an xml file"""
def __init__(self, pretty=True):
"""Set pretty to True if you want an indented XML file"""
self.output = ""
self.stack = []
self.pretty = pretty
def open(self, tag):
"""Add an open tag"""
self.stack.append(tag)
if self.pretty:
self.output += " "*(len(self.stack) - 1);
self.output += "<" + tag + ">"
if self.pretty:
self.output += "\n"
def close(self):
"""Close the innermost tag"""
if self.pretty:
self.output += "\n" + " "*(len(self.stack) - 1);
tag = self.stack.pop()
self.output += "</" + tag + ">"
if self.pretty:
self.output += "\n"
def closeAll(self):
"""Close all open tags"""
while len(self.stack) > 0:
self.close()
def content(self, text):
"""Add some content"""
if self.pretty:
self.output += " "*len(self.stack);
self.output += str(text)
def save(self, filename):
"""Save the data to a file"""
self.closeAll()
fp = open(filename, "w")
fp.write(self.output)
fp.close()
import django.db.models
writer = XMLWriter(pretty=False)
writer.open("djangoexport")
models = django.db.models.get_models()
for model in models:
# model._meta.object_name holds the name of the model
writer.open(model._meta.object_name + "s")
for item in model.objects.all():
writer.open(model._meta.object_name)
for field in item._meta.fields:
writer.open(field.name)
value = getattr(item, field.name)
if value != None:
if isinstance(value, django.db.models.base.Model):
# This field is a foreign key, so save the primary key
# of the referring object
pk_name = value._meta.pk.name
pk_value = getattr(value, pk_name)
writer.content(pk_value)
else:
writer.content(value)
writer.close()
writer.close()
writer.close()
writer.close()
writer.save("export.xml")
This post is a part of the selected archive.
Saturday, June 03, 2006
On web frameworks and AJAX
I recently started working on a new project at home. Its a web application to help out with project management. The two goals were 1) to develop something that I could use for the projects at work and 2) to learn something new. This project was perfect for learning something that I had always wanted to learn more about: Web frameworks and AJAX - both hot areas of Web 2.0 (and yes, although there is a lot of hype around Web 2.0, it is clear that a new web revolution is underway, and it is not just a passing fad).
Given a choice, I prefer to work in Python, so I went around looking for web frameworks in Python (and there are a LOT of them). I finally decided upon django, having heard a lot of good things about it (the fantastic website also helped).
Having worked a bit with it, I can now say WOW. The basic framework for the site is already done and it only took two full days and two nights to get it here. Further, one of the full days was dedicated to designing the look and style of the site, so only a day and two nights were spent on programming. This includes a complete and customised administration area where you can modify any object in the system. Sure, there is still a lot to do, but to still get this far in such a short time has been amazing.
I'm now looking to refine the interface, and that means AJAX. I'm currently looking into the Dojo and Mochikit libraries. I've implemented my first drag and drop using Dojo and in-place editing with Mochikit. That has taken another day. I currently like Mochikit as it is much easier for the beginner to get started with. Dojo looks a lot richer, but its really hard to learn with very scant documentation. Of course, my lack of experience with Javascript (and especially the way OO is done in Javascript) and my familiarity with Python (which Mochikit tries to emulate) may have something to do with that.
After this preliminary experiment, I can say with some confidence that a single person working full time on an application can get a first version out within a month. Capital and resources are no longer major problems. All you need is a good idea. In other words, the next few years will be a great time to be an entrepreneur, much like the years in the late 90s.
Given a choice, I prefer to work in Python, so I went around looking for web frameworks in Python (and there are a LOT of them). I finally decided upon django, having heard a lot of good things about it (the fantastic website also helped).
Having worked a bit with it, I can now say WOW. The basic framework for the site is already done and it only took two full days and two nights to get it here. Further, one of the full days was dedicated to designing the look and style of the site, so only a day and two nights were spent on programming. This includes a complete and customised administration area where you can modify any object in the system. Sure, there is still a lot to do, but to still get this far in such a short time has been amazing.
I'm now looking to refine the interface, and that means AJAX. I'm currently looking into the Dojo and Mochikit libraries. I've implemented my first drag and drop using Dojo and in-place editing with Mochikit. That has taken another day. I currently like Mochikit as it is much easier for the beginner to get started with. Dojo looks a lot richer, but its really hard to learn with very scant documentation. Of course, my lack of experience with Javascript (and especially the way OO is done in Javascript) and my familiarity with Python (which Mochikit tries to emulate) may have something to do with that.
After this preliminary experiment, I can say with some confidence that a single person working full time on an application can get a first version out within a month. Capital and resources are no longer major problems. All you need is a good idea. In other words, the next few years will be a great time to be an entrepreneur, much like the years in the late 90s.
Subscribe to:
Posts (Atom)