Your SlideShare is downloading. ×
Rails vs Django Study Presentation
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Rails vs Django Study Presentation

6,377
views

Published on

Ruby on Rails ("Rails") is the dominant web programming framework for Ruby and, even outside the …

Ruby on Rails ("Rails") is the dominant web programming framework for Ruby and, even outside the
Ruby community, is considered the epitome of the latest generation of high-productivity, open source
web development tools. Django is one of many competing web development frameworks for Python. It
is notable, first, for being highly regarded amongst Python programmers, and second, for being one of
the few of the new generation of frameworks that does not ape Ruby on Rails. Both Rails and Django
claim greatly enhanced productivity, compared with more traditional web development frameworks.
In this paper, we compare the two frameworks from the point of view of a developer attempting to
choose one of the two frameworks for a new project.

Published in: Technology

0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,377
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
52
Comments
0
Likes
8
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. A Rails/Django Comparison by Ben Askins and Alan Green This work is licensed under the Creative Commons Attribution-NonCommercial- ShareAlike 2.5 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. The original version of this presentation is available at http://3columns.net/habitual/docs/Pres2.odp
  • 2. Rails vs. Django
  • 3. We wrote the same application twice
  • 4. Reader Book n m Tag 1 1 n n Reading
  • 5. Development environments different: This was just a single trial. Really need: ● New Mac vs Old Windows laptop ● Multiple developers ● Central Coast vs Cityrail ● Multiple applications ● Multiple environments “Multiple” means “statistically significant” Developer skill level: ● Not identical ● Too advanced to be called ‘beginners’ ● Insufficiently advanced to be ‘typical’ Didn’t consider: ● Performance ● Deployment ● Maintainability LOC and time-to-implement ● Enterprise-friendliness measurements are stupid: ● Not transferable to other developers ● Only rough indicator of complexity Unrepresentative example application: ● Too few pages ● No Atom/RSS feeds ● No public data entry Development practices: ● Didn’t do it the “best way” ● Older versions of Rails and Django ● Didn’t use this or that helpful third party feature Part-time development – start-stop effect and gaps between sessions
  • 6. Some Data
  • 7. Plan
  • 8. $1 000 000
  • 9. US$1 000 000
  • 10. Time to Implement
  • 11. “You don’t understand “This’ll be easy I’ll whip it the power of the built-in up in a weekend.” admin application.” Initial Expectations
  • 12. Hours to Implement 30.00 25.00 HTML Prototype 20.00 15.00 10.00 5.00 0.00 Rails  Django
  • 13. Hours to Implement 30.00 25.00 Develop Test data HTML Prototype 20.00 15.00 10.00 5.00 0.00 Rails  Django
  • 14. Hours to Implement 30.00 25.00 Project set up Develop Test data 20.00 HTML Prototype 15.00 10.00 5.00 0.00 Rails  Django
  • 15. Hours to Implement 30.00 25.00 Models Project set up 20.00 Develop Test data HTML Prototype 15.00 10.00 5.00 0.00 Rails  Django
  • 16. Reader Book n m Tag 1 1 n n Reading
  • 17. Hours to Implement 30.00 25.00 Models Project set up 20.00 Develop Test data HTML Prototype 15.00 10.00 5.00 0.00 Rails  Django
  • 18. Hours to Implement 30.00 25.00 Home page Models 20.00 Project set up Develop Test data HTML Prototype 15.00 10.00 5.00 0.00 Rails  Django
  • 19. Hours to Implement 30.00 25.00 Basic pages Home page 20.00 Models Project set up Develop Test data 15.00 HTML Prototype 10.00 5.00 0.00 Rails  Django
  • 20. Hours to Implement 30.00 25.00 Admin pages Basic pages 20.00 Home page Models Project set up 15.00 Develop Test data HTML Prototype 10.00 5.00 0.00 Rails  Django
  • 21. Hours to Implement 30.00 25.00 Amazon interface Admin pages 20.00 Basic pages Home page Models 15.00 Project set up Develop Test data HTML Prototype 10.00 5.00 0.00 Rails  Django
  • 22. Hours to Implement 30.00 25.00 Data loading code Amazon interface 20.00 Admin pages Basic pages Home page 15.00 Models Project set up Develop Test data 10.00 HTML Prototype 5.00 0.00 Rails  Django
  • 23. Hours to Implement 30.00 25.00 Test, tidy Data loading code 20.00 Amazon interface Admin pages Basic pages 15.00 Home page Models Project set up 10.00 Develop Test data HTML Prototype 5.00 0.00 Rails  Django
  • 24. Hours to Implement 30.00 26:46 25.00 Test, tidy Data loading code 20.00 Amazon interface Admin pages 16:36 Basic pages 15.00 Home page Models Project set up 10.00 Develop Test data HTML Prototype 5.00 0.00 Rails  Django
  • 25. Hours to Implement 30.00 26:46 25.00 Admin Pages Test, tidy Data loading code 20.00 Amazon interface Admin pages 16:36 Basic pages 15.00 Home page Models Project set up 10.00 Develop Test data HTML Prototype 5.00 0.00 Rails  Django
  • 26. Hours to Implement - without Admin 30.00 25.00 Test, tidy Data loading code 20.00 Amazon interface 18:21 Basic pages Home page 15:39 15.00 Models Project set up Develop Test data 10.00 HTML Prototype 5.00 0.00 Rails  Django
  • 27. Lines of Code
  • 28. Lines of Code 800 700 600 Model 500 400 300 200 100 0 Rails Django
  • 29. Lines of Code 800 700 600 View/Controller Model 500 400 300 200 100 0 Rails Django
  • 30. Lines of Code 800 700 600 YAML data loading View/Controller 500 Model 400 300 200 100 0 Rails Django
  • 31. # Reader test data Ben: id: 1 username: benj72 fullname: Ben Askins bio: Eats books for breakfast Alan: id: 2 username: agreen fullname: Alan Green bio: Fond of snakes Fred: id: 3 username: fred fullname: Fred Wilkins bio: Loves a good romantic thriller readers.yml
  • 32. Lines of Code 800 700 600 YAML data loading View/Controller 500 Model 400 300 200 100 0 Rails Django
  • 33. Lines of Code 800 700 600 Authentication YAML data loading 500 View/Controller Model 400 300 200 100 0 Rails Django
  • 34. Lines of Code 800 700 600 Schema Migration Authentication 500 YAML data loading View/Controller 400 Model 300 200 100 0 Rails Django
  • 35. Lines of Code 800 700 600 HTML Helpers/ Template tags 500 Schema Migration Authentication 400 YAML data loading View/Controller Model 300 200 100 0 Rails Django
  • 36. Lines of Code 800 700 600 Templates HTML Helpers/ 500 Template tags Schema Migration 400 Authentication YAML data loading View/Controller 300 Model 200 100 0 Rails Django
  • 37. ● Quicker ● Slightly less code ● Hand-coded admin application ● Concise
  • 38. Browser Browser Web Server Web Server Routes View urls.py Template Controller View Model Model Rails Django Database Database
  • 39. Browser Browser Web Server Web Server Routes View urls.py Template Controller View Model Model Rails Django Database Database
  • 40. ActionController::Routing::Routes.draw # Some imports here do |map| from hrproj.hr import views map.connect '', :controller => "home" urlpatterns = patterns('', # restful resources (r'^$', views.index), map.resources :books do |books| books.resources :readings (r'^readers/$', views.reader_list), end (r'^tags/$', views.tag_list), (r'^books/$', views.book_list), map.resources :readers do |readers| readers.resources :reader_images (r'^readers/(?P<username>.*)/$', end views.reader_detail), (r'^tags/(?P<slug>.*)/$', map.resources :tags views.tag_detail), end (r'^books/(?P<slug>.*)/$', views.book_detail), ) /books/hitchhikers-guide-to-the-galaxy URL Configuration
  • 41. Browser Browser Web Server Web Server Routes View urls.py Template Controller View Model Model Rails Django Database Database
  • 42. class BooksController < ApplicationController before_filter :find_book def book_detail(request, slug): book = get_object_or_404(Book, slug=slug) def show queryset = ReadingOccasion.objects @reading_paginator, @readings = paginate .filter(book=book) :readings, .order_by('finished') :conditions => ["book_id = ?", return standard_view( @book.id] request, queryset, end 'book_detail.html', 'readingoccasion', private book=book) def find_book @book = Book.find_by_title(params[:id]) end end Controller / View Function
  • 43. Browser Browser Web Server Web Server Routes View urls.py Template Controller View Model Model Rails Django Database Database
  • 44. class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED, num_in_admin=1) class Reading < ActiveRecord::Base finished = models.DateField(   belongs_to :book core=True)   belongs_to :reader reading_time = models.FloatField( end max_digits=5, decimal_places=2, core=True, blank=True) notes = models.TextField( maxlength=2000, blank=True)
  • 45. class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED, num_in_admin=1) class Reading < ActiveRecord::Base finished = models.DateField(   belongs_to :book core=True)   belongs_to :reader reading_time = models.FloatField( end max_digits=5, decimal_places=2, core=True, blank=True) notes = models.TextField( maxlength=2000, blank=True)
  • 46. Schema evolution
  • 47. class CreateReadings < ActiveRecord::Migration def self.up create_table :readings do |t| t.column "book_id", :integer t.column "reader_id", :integer t.column "date_read", :datetime t.column "reading_time", :integer t.column "notes", :text end end def self.down drop_table :readings end end Schema is Versioned
  • 48. ● Drop database tables ● Re-create tables manage.py syncdb python yaml/load_data.py ● In production, you write migration DDL by hand Django DB evolution
  • 49. Browser Browser Web Server Web Server Routes View urls.py Template Controller View Model Model Rails Django Database Database
  • 50. books/show.rhtml: <%= render :partial => 'readings/list', :locals => {:key_field => "Reader"} %> readings/_list.rhtml: book_detail.html: <tbody> <tbody> <%= render :partial => 'readings/reading', {% for ro in readingoccasion_list %} :collection => @readings, <tr> :locals => {:key_field => key_field} %> <td class="name_col"> </tbody> <a href="{{ ro.reader.get_absolute_url }}"> {{ ro.reader.name }} readings/_reading.rhtml: </a> <tr> </td> <td class="name_col"> <td class="date_col"> <% if key_field == "Book" %> {{ ro.finished|date:"j M Y" }} <%= link_to reading.book.title, </td> book_url(reading.book) %> <td class="num_col"> <% else %> {{ ro.reading_time }} <%= link_to reading.reader.fullname, </td> reader_url(reading.reader) %> <td>{% firstof ro.notes "-" %}</td> <% end %> </tr> </td> {% endfor %} <td class="date_col"> </tbody> <%= reading.date_read_for_display %> </td> <td class="num_col"> <%= reading.reading_time %> </td> <td><%= reading.notes %></td> </tr> View / Template
  • 51. readers/show.rhtml: <%= render :partial => 'readings/list', :locals => { :key_field => "Book" } %> reader_detail.html: <tbody> {% for ro in readingoccasion_list %} <tr> <td class="name_col"> <a href="{{ ro.book.get_absolute_url }}"> {{ ro.book.title }} </a> </td> <td class="date_col"> {{ ro.finished|date:"j M Y" }} </td> <td class="num_col"> {{ ro.reading_time }} </td> <td>{% firstof ro.notes "-" %}</td> </tr> {% endfor %} </tbody> View / Template
  • 52. And the other bits
  • 53. ● Can save a lot of time ● Good looking result ● Does simple CRUD quite well but... ● Only does simple CRUD ● Only does simple relationships ● Security not fine-grained ● Not intended for public-facing pages Django Admin application
  • 54. page.visual_effect :fade, dom_id(@tag) page.replace_html “feedback”, “Tag Deleted” page.visual_effect :appear, “feedback”, :queue => :end page.visual_effect :fade, “feedback”, :queue => :end AJAX
  • 55. Books on Amazon 11 10 9 8 7 6 5 4 3 2 1 0 Rails Django
  • 56. Jobs on seek.com.au 120 110 100 90 80 70 60 50 40 30 20 10 0 Ruby Ruby on Rails Python Django
  • 57. ● Began Oct 2003 ● Began Fall 2003 ● DHH ● Adrian and Simon – in reaction to PHP – “ditched” PHP ● Extracted from ● Extracted from Basecamp ljworld.com ● Released: July 2004 ● Released: July 2005 ● 1.0 shipped Dec 2005 ● 1.0 not yet shipped – Latest is 1.1.6 – Latest is 0.95 History
  • 58. Conclusion
  • 59. Already using Rails?
  • 60. Already using Rails?
  • 61. Already using Django?
  • 62. Already using Django?
  • 63. Already know Ruby?
  • 64. Already know Ruby?
  • 65. Already know Python?
  • 66. Already know Python?
  • 67. Private admin pages?
  • 68. Private admin pages?
  • 69. Simple AJAX?
  • 70. Simple AJAX?
  • 71. Non-programming web designers?
  • 72. Non-programming web designers?
  • 73. Evolving Schema?
  • 74. Evolving Schema?
  • 75. Maturity
  • 76. Maturity – product, community, and market
  • 77. Maturity – product, community, and market
  • 78. Concise or Explict?
  • 79. Concise Explicit
  • 80. Still can’t choose?
  • 81. Thanks!
  • 82. ● Photos – Sad puppy: http://www.flickr.com/photos/sookie/108356632/ ● Software – David A. Wheeler’s Sloccount ● http://www.dwheeler.com/sloccount/ – HTML Template by Andreas Viklund ● All of the paper reviewers ● Our bosses: – Cirrus Technologies – Karen Askins With thanks to
  • 83. ● “The Builders of Basecamp” – http://www.oreillynet.com/pub/a/network/2005/03/10/base ● Snakes and Rubies presentation – http://video.google.com/videoplay?docid=2939556954580 ● Django FAQ – http://www.djangoproject.com/documentation/faq/
  • 84. Lots of interest in these two frameworks Similar in some ways Different in others How to choose between them? Why Comparing?
  • 85. This is some Ruby code This is some Python code
  • 86. Bonus Material
  • 87. def standard_view(request, queryset, template_name, template_object_name, **extra_context): """ Wrapper around the object_list generic view. """ return object_list(request, queryset=queryset, allow_empty=True, template_name=template_name, template_object_name=template_object_name, page=get_page(request), paginate_by=PAGE_SIZE, extra_context=extra_context) def get_page(request): """ Determines the current page number. """ return int(request.GET.get('page', 1)) standard_view
  • 88. Hours to Implement 30.00 20:40 25.00 Test, tidy Data loading code 20.00 Amazon interface Admin pages 10:30 Basic pages 15.00 Home page Models Project set up 10.00 Develop Test data HTML Prototype 5.00 0.00 Rails  Django