說到Django與Rails的比較,最常被拿出來討論的就是他的MTV架構
與我們熟知的MVC略有不同(如果你是先接觸Django,當然可能會有相反的認知)
一般來說我們會做以下的對照:
結構參照 | Rails | Django |
---|---|---|
模型(Data Access Logic) | model | model |
視圖(Presentation Logic) | view | template |
控制器(Business Logic) | controller | view |
這也是MTV的由來(Model-Template-View)
不用特別觀察也可以發現這邊兩種不同架構view的角色不同
而model則是一致
但也有另外一種說法
認為view與template事實上都是對應視圖,而控制器應該是django本身
所以對照圖如下:
結構參照 | Rails | Django |
---|---|---|
模型(Data Access Logic) | model | model |
視圖(Presentation Logic) | view | template、view |
控制器(Business Logic) | controller | Django itself |
但我個人基本上是不能接受這種說法的
先不說這樣無法算是MVT而應該是MVTD
如果我們看看一個傳統的Django view的例子:
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello from Django!')
會發現與Rails的controller基本上是做一樣的事情
class UsersController < ApplicationController
def index
@test = "Hello rails"
end
end
在安裝完環境,開始創建第一個Django專案的時候
我注意到一個很少人比較的差異
就是Django有Project and apps的概念,也就是一個專案(project)下可能多有個apps
但rails專案下就是一個app,很少有聽人實作過複數以上apps的案例
按照django的說法,例如Facebook依照功能有以下的apps:
如果我們未來要追加購物功能,accounts
這個app就可以重複使用。
當這樣的情境在rails之下,我們依然會視其為同一個app
只是不同部分的功能區塊
第一次看到這種區分方式覺得很貼心,但是轉念一想
九成以上的專案其實沒有這種需求
按照rails「慣例優先於設定」的精神,自然會不喜歡這種設計
如果我們比較創建專案的指令:
~/projects$ django-admin.py startproject mysite
~/projects$ cd mysite
~/projects/mysite$ python manage.py startapp djangoapp
在rails,我們只需要:
~/projects$ rails new railsapp
就可以建立一個名為railsapp的專案
我覺得從產生一個新專案開始,就可以知道為什麼rails這麼迷人
如果一行可解決問題,那就不要兩行
我都還沒提到Django在startapp以後,還需要到settings.py
去手動註冊新app
# mysite/settings.py
...
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djangoapp',
)
我敢打賭一定很多Django的新手忘記這步,然後奇怪server打開怎麼沒有東西
接續著對開發者的友善程度(或稱開發的簡便程度)
講嚴格一點,我認為光是CLI之前還需要強調語言才能用就已經很冗余了(不過這一點Laravel也相同)
比方說一些常見的指令:
python manage.py -h <command_name>
python manage.py runserver
python manage.py startapp <app_name>
而在rails 相對應的指令為:
rails h
rails s
rails new <app_name>
長度只有一半,輸入的時間就節省一半
我當然知道Django也會有些套件可以做到類似的事情,例如django-shortcuts
但當這件事還需要考慮套件時,先天上就已經輸了
rails會在下一版成為預設(好吧,也或許我被rails寵壞了)
除了CLI以外,我還觀察到新建app與Template資料夾以後
都需要到settings.py
修改設定
# settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates').replace('\\', '/')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
其中的DIR預設為[]
,
要改為[os.path.join(BASE_DIR, 'templates').replace('\\', '/')]
既然創建app與新增Template資料夾是每個專案幾乎固定的動作
環境根本就可以主動先去確認約定的檔案名稱是否存在
少數特例再使用設定就好
況且,九成九以上的專案都會用到Template資料夾
為什麼不乾脆一開始就新增好成為預設
還要讓使用者自己新增?
倒數第二點
我發現Rails有一個很方便的工具,但是Django沒有(或是我目前沒有在教學文件上找到)
就是關於動態路由的對應,Django需要一條一條寫,例如:
#urls.py
from trips.views import hello_world, home, post_detail
urlpatterns = [
...
url(r'^post/(?P<pk>\d+)/$', post_detail, name='post_detail'),
]
但是在rails我們有個方便的工具Resoruce
#routes.rb
Rails.application.routes.draw do
resources :post
end
只要短短一行,就產生了七種常用的路由,還可以用only
或except
去做調整
甚至可以做套疊
不僅大大節省了開發時間,也讓程式碼顯得更簡潔
黑了Django這麼多,在最後一點試圖平反一下
我還是有發現一點我覺得很不錯,而Rails沒有的
就是Django預設內建的Admin page
雖然我不知道實務上專案常不常用到
但至少有這個開發工具我覺得是相當方便的
雖然Rails要寫出類似的東西或是使用Gem也不會很麻煩
但這點確實是Django比較貼心的地方
除此之外
Rails慣例優於設定的精神簡直大勝!
這是我的觀察啦,理性勿戰
黑了這麼多,然後說理性勿戰。XD
用Django有個好處,就是在windows開發也一點問題也沒有,可是在網路上看Rail對初學者的建議是有錢用MAC,沒錢用linux。這點是我當初選Django的原因。不知道現實狀況是怎樣呢?
Settings.py那節說錯了。
你只要在app建完,註冊進去,然後在app裡面建templates資料夾就可以了。
(不過我也不知道官方不在產生的時候就把app註冊進去的理由是什麼,因為我找不到建好app不註冊進去的理由...)
Django的想法是希望你專案建完就建app,不同的功能由不同的app去管理。
也就是「網站」=「project」,然後裡面的「功能」=「app」。
在project裡建templates資料夾反而少見,通常是對app去建的。
像我的習慣是使用者登入、管理會建一個app,各種功能會各建一個。
這樣的好處是就算你網站功能再複雜,光看資料夾名稱你就已經知道你要改啥了。
感謝回饋!能用Windows開發真是一個優點,我當初為了開發rails果斷買了MAC
project與app經過你這樣解釋我更理解了,確實挺方便的。
Settings.py的部分,我是參考這邊的學習手冊
你的意思是只要在app下建Template資料夾就可以了,不需要到settings.py註冊嗎?
要註冊app,但不用自己手動填入「os.path.join(BASE_DIR, 'templates').replace('\', '/')」
app註冊完,Django會自己去找app裡面的templates資料夾。
在project層級下建templates反而比較麻煩,在app下建比較容易,這也算是證明我上面講的Django對於project和app的想法。
說到自己手動填入路徑,我想再講個方便的點。
Django的settings.py本身就是個可執行的python檔,所以設定是可以依照你的狀態去改的。
例如我測試機在windows,實際佈署是linux,我可以利用模組去看我的project目前在什麼機器,然後參數寫在同一份設定,去用if來判斷就好。
甚至很多全站共用的參數,你都可以寫在settings.py去import進去,可以重複利用。
另外幫python/Django再辯駁一點:你如果深入一點寫python,你會發現python很注重code的可讀性,有時寧願犧牲一點簡潔,也要讓可讀性變高。
拿你的兩個例子來說:
class UsersController < ApplicationController
def index
@test = "Hello rails"
end
end
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello from Django!')
Rail的確比較簡潔,但是python你不得不說如果你寫過其他語言,你應該會看得懂,比較符合慣例和虛擬碼。
這是當初設計語言者的哲學和取捨。
python甚至為了提高可讀性,出了一個規範,叫 PEP 8,而且大部分的python使用者都蠻樂意遵守的。
(有興趣的話還可以看看PEP 20)
然後Django Admin在Django 2.0之後變成RWD了。
雖然我還是只有測試的時候會用,開放給別人管後台的時候不給。
(沒辦法,使用者有時你真的沒辦法教育,還是寫個讓他一看就懂的後台給他比較省事。)
不過你現在這樣每個框架一天,你要怎麼撐過30天的鐵人賽啊。XD
我現在覺得相當痛苦 QQ