Rails vs Django Study Presentation

Post on 19-May-2015

6,468 views 4 download

Tags:

description

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.

transcript

A Rails/Django Comparisonby 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

Django Rails vs.

We wrote the same application twice

TagBook

Reading

Reader n m

nn

11

Developer skill level:● Not identical● Too advanced to be called ‘beginners’● Insufficiently advanced to be ‘typical’

Development environments different:● New Mac vs Old Windows laptop● Central Coast vs Cityrail

Part-time development – start-stop effect and gaps between sessions

Didn’t consider:● Performance● Deployment● Maintainability● Enterprise-friendliness

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

This was just a single trial. Really need:● Multiple developers● Multiple applications● Multiple environments

“Multiple” means “statistically significant”

LOC and time-to-implement measurements are stupid:

● Not transferable to other developers● Only rough indicator of complexity

Some Data

Plan

$1 000 000

US$1 000 000

Time to Implement

Initial Expectations

“This’ll be easy I’ll whip it up in a weekend.”

“You don’t understand the power of the built-in

admin application.”

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Models Project set up Develop Test data HTML Prototype

TagBook

Reading

Reader n m

nn

11

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Basic pages Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

26:46

16:36

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

Admin PagesAdmin Pages26:46

16:36

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement - without Admin

Test, tidy Data loading code Amazon interface Basic pages Home page Models Project set up Develop Test data HTML Prototype

18:21

15:39

Lines of Code

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

Model

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

View/ControllerModel

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

YAML data loading View/ControllerModel

readers.yml

# Reader test dataBen: id: 1 username: benj72 fullname: Ben Askins bio: Eats books for breakfastAlan: id: 2 username: agreen fullname: Alan Green bio: Fond of snakesFred: id: 3 username: fred fullname: Fred Wilkins bio: Loves a good romantic thriller

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

YAML data loading View/ControllerModel

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

Authentication YAML data loading View/ControllerModel

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

Schema Migration Authentication YAML data loading View/ControllerModel

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

HTML Helpers/ Template tags Schema Migration Authentication YAML data loading View/ControllerModel

Rails Django0

100

200

300

400

500

600

700

800

Lines of Code

Templates HTML Helpers/ Template tags Schema Migration Authentication YAML data loading View/ControllerModel

● Hand-coded admin application

● Concise

● Quicker● Slightly less code

Database

Web Server

Routes View

Controller

Model

Browser

Database

Web Server

urls.py Template

View

Model

Browser

Rails Django

Database

Web Server

Routes View

Controller

Model

Browser

Database

Web Server

urls.py Template

View

Model

Browser

Rails Django

ActionController::Routing::Routes.draw do |map|

map.connect '', :controller => "home"

# restful resources map.resources :books do |books| books.resources :readings end map.resources :readers do |readers| readers.resources :reader_images end map.resources :tagsend

# Some imports herefrom hrproj.hr import views

urlpatterns = patterns('',

(r'^$', views.index),

(r'^readers/$', views.reader_list), (r'^tags/$', views.tag_list), (r'^books/$', views.book_list),

(r'^readers/(?P<username>.*)/$', views.reader_detail), (r'^tags/(?P<slug>.*)/$', views.tag_detail), (r'^books/(?P<slug>.*)/$', views.book_detail),)

URL Configuration

/books/hitchhikers-guide-to-the-galaxy

Database

Web Server

Routes View

Controller

Model

Browser

Database

Web Server

urls.py Template

View

Model

Browser

Rails Django

Controller / View Function

class BooksController < ApplicationController before_filter :find_book

def show @reading_paginator, @readings = paginate :readings, :conditions => ["book_id = ?", @book.id] end

private def find_book @book = Book.find_by_title(params[:id]) end

end

def book_detail(request, slug): book = get_object_or_404(Book, slug=slug) queryset = ReadingOccasion.objects \ .filter(book=book) \ .order_by('finished') return standard_view( request, queryset, 'book_detail.html', 'readingoccasion', book=book)

Database

Web Server

Routes View

Controller

Model

Browser

Database

Web Server

urls.py Template

View

Model

Browser

Rails Django

class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED,

num_in_admin=1) finished = models.DateField( core=True) reading_time = models.FloatField(

max_digits=5,decimal_places=2,

core=True, blank=True) notes = models.TextField(

maxlength=2000, blank=True)

class Reading < ActiveRecord::Base  belongs_to :book  belongs_to :readerend

class ReadingOccasion(models.Model): reader = models.ForeignKey(Reader) book = models.ForeignKey(Book, edit_inline=models.STACKED,

num_in_admin=1) finished = models.DateField( core=True) reading_time = models.FloatField(

max_digits=5,decimal_places=2,

core=True, blank=True) notes = models.TextField(

maxlength=2000, blank=True)

class Reading < ActiveRecord::Base  belongs_to :book  belongs_to :readerend

Schema evolution

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 endend

Schema is Versioned

Django DB evolution

● Drop database tables● Re-create tables

manage.py syncdbpython yaml/load_data.py

● In production, you write migration DDL by hand

Database

Web Server

Routes View

Controller

Model

Browser

Database

Web Server

urls.py Template

View

Model

Browser

Rails Django

books/show.rhtml:<%= render :partial => 'readings/list', :locals => {:key_field => "Reader"} %>

readings/_list.rhtml:<tbody> <%= render :partial => 'readings/reading', :collection => @readings, :locals => {:key_field => key_field} %></tbody>

readings/_reading.rhtml:<tr> <td class="name_col"> <% if key_field == "Book" %> <%= link_to reading.book.title, book_url(reading.book) %> <% else %> <%= link_to reading.reader.fullname, reader_url(reading.reader) %> <% end %> </td> <td class="date_col"> <%= reading.date_read_for_display %> </td> <td class="num_col"> <%= reading.reading_time %> </td> <td><%= reading.notes %></td></tr>

book_detail.html:<tbody>{% for ro in readingoccasion_list %} <tr> <td class="name_col"> <a href="{{ ro.reader.get_absolute_url }}"> {{ ro.reader.name }} </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

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

And the other bits

Django Admin application

● Can save a lot of time● Good looking result● Does simple CRUD quite wellbut...● Only does simple CRUD● Only does simple relationships ● Security not fine-grained ● Not intended for public-facing pages

AJAX

page.visual_effect :fade, dom_id(@tag)page.replace_html “feedback”, “Tag Deleted”page.visual_effect :appear, “feedback”, :queue => :endpage.visual_effect :fade, “feedback”, :queue => :end

Rails Django

0123456789

1011

Books on Amazon

Ruby Ruby on Rails Python Django0

10

20

30

40

50

60

70

80

90

100

110

120

Jobs on seek.com.au

History

● Began Oct 2003● DHH

– in reaction to PHP● Extracted from

Basecamp● Released: July 2004● 1.0 shipped Dec 2005

– Latest is 1.1.6

● Began Fall 2003● Adrian and Simon

– “ditched” PHP● Extracted from

ljworld.com● Released: July 2005● 1.0 not yet shipped

– Latest is 0.95

Conclusion

Already using Rails?

Already using Rails?

Already using Django?

Already using Django?

Already know Ruby?

Already know Ruby?

Already know Python?

Already know Python?

Private admin pages?

Private admin pages?

Simple AJAX?

Simple AJAX?

Non-programming web designers?

Non-programming web designers?

Evolving Schema?

Evolving Schema?

Maturity

Maturity – product,community, and market

Maturity – product,community, and market

Concise or Explict?

Concise Explicit

Still can’t choose?

Thanks!

With thanks to

● 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

● “The Builders of Basecamp”– http://www.oreillynet.com/pub/a/network/2005/03/10/basecamp.html

● Snakes and Rubies presentation– http://video.google.com/videoplay?docid=2939556954580527226

● Django FAQ– http://www.djangoproject.com/documentation/faq/

Why Comparing?

Lots of interest in these two frameworks

Similar in some ways

Different in others

How to choose between them?

This is some Ruby code This is some Python code

Bonus Material

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

Rails  Django 0.00

5.00

10.00

15.00

20.00

25.00

30.00

Hours to Implement

Test, tidy Data loading code Amazon interface Admin pages Basic pages Home page Models Project set up Develop Test data HTML Prototype

20:40

10:30