shabda
Comments
Reactions

The Rails and Django models layer Rosseta stone

By : Shabda Raaj

Rails Active records and Django models are more similar than they are different. This is a quick guide to converting between Rails 3 and Django 1.2, and is available on github at http://github.com/uswaretech/Acts-as-Django

Defining models

Both Django and Rails keep the canonical database representation in ruby or python.

#Django

class Post(models.Model):
    name = models.CharField(max_length = 100, )
    slug = models.CharField(max_length = 100, )
    body = models.TextField()

class Comments(models.Model):
    post = models.ForeignKey(Post)
    username = models.CharField(max_length = 100, )
    comment = models.TextField()

#Rails

#db/schema.rb
ActiveRecord::Schema.define(:version => 20100319195739) do

  create_table "comments", :force => true do |t|
    t.string   "username"
    t.text     "comment"
    t.integer  "post_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "posts", :force => true do |t|
    t.string   "name"
    t.string   "slug"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

#In apps models
class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

The main difference is that Django keeps it one file, while rails has it split over many files. In Django, the foreign key is specified only on the Child model via models.ForeignKey but in Rails both sides of relationship need to be specified via has_many and belongs_to.

Create a object without saving it

In [1]: from blog.models import *

In [2]: post = Post()

In [3]: print post.id
None

irb(main):001:0> post = Post.new
=> #<Post id: nil, name: nil, slug: nil, body: nil, created_at: nil, updated_at: nil>
irb(main):002:0> post.id
=> nil

Set values and save to the database

In [4]: post.name = "Hello"

In [5]: post.slug = "hello"

In [6]: post.body = "Hello, this is a post"

In [8]: post.save()

In [9]: post.id
Out[9]: 1

irb(main):001:0> post = Post.new
=> #<Post id: nil, name: nil, slug: nil, body: nil, created_at: nil, updated_at: nil>
irb(main):002:0> post.id
=> nil
irb(main):003:0> post.name = "Hello"
=> "Hello"
irb(main):004:0> post.slug = "hello"
=> "hello"
irb(main):005:0>  post.body = "Hello, this is a post"
=> "Hello, this is a post"
irb(main):006:0> post.save()
=> true
irb(main):007:0> post.id
=> 2

There is not much to see here, both DJango and Rails create the object in essentially the same way. Until you call save, the objects are not saved to the database.

Find object by the primary key.

In [10]: Post.objects.get(id = 1)
Out[10]: <Post: Post object>

irb(main):008:0> pst = Post.find(2)
=> #<Post id: 2, name: "Hello", slug: "hello", body: "Hello, this is a post", created_at: "2010-03-19 20:11:34", updated_at: "2010-03-19 20:11:34">

What Rails calls find, Django calls get.

More create methods

In [12]: Post.objects.create(name="Hi", slug="hi", body="Hi hi hi.")
Out[12]: <Post: Post object>

irb(main):012:0> Post.create(:name=>"Hi", :slug=>"Hi", :body=>"Hi hi hi")
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">

In [14]: Post.objects.get_or_create(name="Hi")
Out[14]: (<Post: Post object>, False)

irb(main):015:0> Post.find_or_create_by_name("Hi")
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">

You can create in one step without calling save via a create in both Rails and Django. While rails has dynamically named methods, Django accepts named parameters in filter and get_or_create.

More find methods

In [15]: Post.objects.filter(id__in = [1, 2, 3])
Out[15]: [<Post: Post object>, <Post: Post object>]

irb(main):017:0> Post.find(1, 2, 3)
=> [#<Post id: 1, name: nil, slug: nil, body: nil, created_at: "2010-03-19 19:58:31", updated_at: "2010-03-19 19:58:31">, #<Post id: 2, name: "Hello", slug: "hello", body: "Hello, this is a post", created_at: "2010-03-19 20:11:34", updated_at: "2010-03-19 20:11:34">, #<Post id: 3, name: nil, slug: nil, body: nil, created_at: "2010-03-19 20:16:04", updated_at: "2010-03-19 20:16:04">]

In [16]: Post.objects.get(name="Hi")
Out[16]: <Post: Post object>

irb(main):023:0> Post.find_by_name("Hi")
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">

In [17]: Post.objects.all()
Out[17]: [<Post: Post object>, <Post: Post object>]

irb(main):024:0> Post.find(:all)
=> [#<Post id: 1, name: nil, slug: nil, body: nil, created_at: "2010-03-19 19:58:31", updated_at: "2010-03-19 19:58:31">, #<Post id: 2, name: "Hello", slug: "hello", body: "Hello, this is a post", created_at: "2010-03-19 20:11:34", updated_at: "2010-03-19 20:11:34">, #<Post id: 3, name: nil, slug: nil, body: nil, created_at: "2010-03-19 20:16:04", updated_at: "2010-03-19 20:16:04">, #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">]

In [18]: pp = Post.objects.filter(name="Hi")

In [19]: pp
Out[19]: [<Post: Post object>]
In [20]: pp[0]
Out[20]: <Post: Post object>

irb(main):032:0> pp = Post.where({:name=>"Hi"})
=> #<ActiveRecord::Relation:0xb6aedc04 @arel=nil, @select_values=[], @last=nil, @order_values=[], @group_values=[], ...
irb(main):033:0> pp[0]
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">

In [21]: Post.objects.filter(name__in = ["Hi", "Hello"])
Out[21]: [<Post: Post object>, <Post: Post object>]

irb(main):034:0> pp = Post.where({:name=>["Hi", "Hello"]})
=> #<ActiveRecord::Relation:0xb6ae4c6c @arel=nil, @select_values=
....
irb(main):035:0> pp[0]
=> #<Post id: 2, name: "Hello", slug: "hello", body: "Hello, this is a post", created_at: "2010-03-19 20:11:34", updated_at: "2010-03-19 20:11:34">
irb(main):036:0> pp[1]
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">

In [29]: p = Post.objects.filter(name__in = ["Hi", "Hello"]).only("name")

irb(main):041:0> pp = Post.where({:name=>["Hi", "Hello"]}).select("name")

The query capability and syntax are similar with major differences being,

  1. Rails has dynamically named finders, while Django accepts keyword arguments for same.
  2. SQL operators like in are fired by __ in Django, while Rails infers it based on the data type.

Limit, offset and order

In [30]: p = Post.objects.filter(name__in = ["Hi", "Hello"])[:1]

In [31]: p
Out[31]: [<Post: Post object>]

pp = Post.where({:name=>["Hi", "Hello"]}).select("name").limit(1)

irb(main):049:0> pp[0]
=> #<Post name: "Hello">
irb(main):050:0> pp[1]
=> nil

=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">
irb(main):067:0> pp = Post.where({:name=>["Hi", "Hello"]}).limit(1).offset(1)

irb(main):067:0> pp[0]
=> #<Post id: 4, name: "Hi", slug: "Hi", body: "Hi hi hi", created_at: "2010-03-19 20:17:31", updated_at: "2010-03-19 20:17:31">
irb(main):068:0> pp[1]
=> nil

In [34]: p = Post.objects.filter(name__in = ["Hi", "Hello"])[1:2]

In [35]: p[0].name
Out[35]: u'Hi'

In [36]: p[1].name
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)

/home/shabda/Code/Django/Weblog/<ipython console> in <module>()

/usr/local/lib/python2.6/dist-packages/django/db/models/query.py in __getitem__(self, k)
    185             qs = self._clone()
    186             qs.query.set_limits(k, k + 1)
--> 187             return list(qs)[0]
    188         except self.model.DoesNotExist, e:
    189             raise IndexError(e.args)

IndexError: list index out of range

In [39]: p = Post.objects.order_by("name")[1:2]

In [40]: p
Out[40]: [<Post: Post object>]

irb(main):069:0> pp = Post.order("name").limit(1).offset(1)

Again fairly similar, both Django and rails provide ordering, offset and limits, while Django does this via array slicing, Rails does this via functions. Also both Django and Rails allow method chaining, and Sql is only evaluated lazily when needed.

Specifying Model associations.

Django: models.ForeignKey
Rails: belongs_to

Django: models.ManyToManyField
Rails: has_and_belongs_to_many

Django: models.OneToOneField
Rails: has_one

Django: No needed
Rails: has_many

Again Rails and Django are similar with Django automatically inferring the reverse relationships.

Polymorphic Associations and Generic Relations

You possibly have pictures in your application which can be attached to any object. Both Django and Rails provide options for it via Polymorphic Associations and Generic Relations

class Picture(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

class Article(models.Model):
    body = models.TextField()
    picture =  generic.GenericRelation(Picture)

class BioGraphy(models.Model):
    bio  = models.TextField()
    picture = generic.GenericRelation(Picture)

class Picture < ActiveRecord::Base
  belongs_to :imageable, :polymorphic => true
end

class Employee < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end

class Product < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end

Self Joins

Self joins are a special case of Foreign key where a Object has a relationship to itself. Both Django and Rails handle it normally via their FK mechanisms

class Employee(models.Model):
    manager = models.ForeignKey("self", related_name = "subordinates")

class Employee < ActiveRecord::Base
  has_many :subordinates, :class_name => "Employee",
    :foreign_key => "manager_id"
  belongs_to :manager, :class_name => "Employee"
end

References

guides.rails.info djangoproject.com/documentation/


Related Posts


Can we help you build amazing apps? Contact us today.

Comments

Pour les dames qui adorent Sacs ¨¤ main personnalis¨¦s

The Rails and Django models layer Rosseta stone - Agiliq Blog | Django web app development

commmenttor
Cooper

An envelope famvir 500 Tyler said agreement by countries on a global market-based solution, the details of which would need to be worked out, was preferable to regional measures such as the EU's controversial Emissions Trading Scheme.
hoodia 57 That isn&#8217;t to say Obama&#8217;s getting no respite; his approval rating on the economy fell as low as 35 percent back in fall 2011, and his predecessor, George W. Bush, saw 22 percent approval on the economy in September 2008.

commmenttor

Reactions

uswaretech

http://bit.ly/9YB9gJ A comparision and conversion doc between Django and rails models. on github at http://bit.ly/dAQQUg

This comment was originally posted on Twitter

DjangoIreland

The Rails and Django models layer Rosseta stone — The Usware Blog … http://bit.ly/cI5PMY

This comment was originally posted on Twitter

uswaretech_blog

The Rails and Django models layer Rosseta stone: Rails Active records and Django models are more similar than they… http://bit.ly/aRJey3

This comment was originally posted on Twitter

jobboardshq

http://bit.ly/9YB9gJ A comparision and conversion documentc between DJango and Rails models layer. On Github as well at http://bit.ly/dAQQUg

This comment was originally posted on Twitter

thoas

#django models layer in comparison with #rails Active Record http://bit.ly/bXBtZP

This comment was originally posted on Twitter

djangostories

The Rails and Django models layer Rosseta stone: http://bit.ly/d7aq6c

This comment was originally posted on Twitter

bkonkle

A nifty guide to Rails DB model definitions, compared to Django’s model definitions. This will come in handy soon… http://bit.ly/9T1y4P

This comment was originally posted on Twitter

seanodonnell

surprised by how similar ActiveRecord and Django models are http://short.ie/8d04gr

This comment was originally posted on Twitter

johndagostino

The Rails and Django models layer Rosseta stone http://uswaretech.com/blog/2010/03/the-rails-and-django-models-layer-rosseta-stone/

This comment was originally posted on Twitter

PatriceGirard

Model Django vs Active Record de Rails, http://bit.ly/atkFb2.. Pourquoi des ORM pour faire en SQL ce que MongoDB fait nativement?

This comment was originally posted on Twitter

djangostories

The Rails and Django models layer Rosseta stone — The Usware Blog – Django Web Development: http://bit.ly/aWhuzr

This comment was originally posted on Twitter

scalar

a good comparison between rails and django orm layers: http://bit.ly/bup7g6

This comment was originally posted on Twitter

pilhofer

Interesting comparison of Rails & Django models. Coke vs. Pepsi, really. http://bit.ly/9YB9gJ

This comment was originally posted on Twitter

Post a comment Name :

Email :

Your site url:

Comment :

© Agiliq, 2009-2012