建立 Controller

我們已經有了一個 Transaction model & seed, 再來就是做 Controller。

在 Masonite 建立 Controller 相當簡單:

$ craft controller Transactoin --resource

依照 Masonite 的約定,上面這行命令會建立 app/http/controllers/TransactionController.py,並且由於命令後面追加的 --resource 參數,Masonite 也幫我們在 TransactionController 內加上了基本的 CRUD 方法。

路由

用戶在瀏覽器請求 http://127.0.01:8000/transaction/ 時,會先由 route 來決定要分配給哪個 Contrller 的哪個方法,雖然目前 TransactionController 內容都是空的,不過我們在此先行定義 Transaction 的路由規則,後面再來寫具體的 TransactionController method。

路由檔案在 routes/web.py,在檔案內加入一行:

Get('/transactions', 'TransactionController@index')

這行應該很好理解:在瀏覽器 GET /transaction 這個位址的時候,交由 TransactionController 的 index() 方法來處理。

HTTP 動作(GET、POST 等等…)與 Controller 方法之間的對應關係也有一些既有的慣例存在,這些慣例可以參考 Laravel 的文件:RESTful Resource Controllers

Index 方法

回到 TransactionController,裡面的 index() 應該是空白的長這樣:

def index(self, request: Request, auth: Auth, view: View):
    """Show several resource listings
    ex. Model.all()
        Get().route("/index", TransactionController)
    """

    psss

接下來這裡想要的設計是,如果用戶已登入,則顯示出他名下的交易紀錄;如果用戶未登入,則跳轉到登入表單畫面。

用戶認證

來做用戶認證,在 TransactionController 最前面先 import 模組:

from masonite.auth import Auth
from masonite.request import Request

再回到 index() 加入判斷登入的敘述,如果未登入,跳轉到網址 /login;如果已登入,讓變數 user 指向這位登入的用戶:

def index(self, request: Request, auth: Auth):
    """Show several resource listings
    ex. Model.all()
        Get().route("/index", TransactionController)
    """

    if not auth.user():
        return request.redirect('/login')
    user = auth.user()

關於用戶認證的部份,除了在 controller 做判斷外,因應不同的需求,也可能在 route 或 view 裡面做判斷,Masonite 原廠文件有更多關於這方面的敘述。

查詢已登入用戶的交易紀錄

前一節的最後一行已經把已登入用戶派給一個變數 user,現在利用 ORM 來查詢這位 user 大大的交易紀錄。一樣要先引用模組:

from app.Transaction import Transaction

這是事前已經定義好的 Transaction model,有了它才能做查詢。

index() 加入查詢的敘述:

def index(self, request: Request, auth: Auth):
    """Show several resource listings
    ex. Model.all()
        Get().route("/index", TransactionController)
    """

    if not auth.user():
        return request.redirect('/login')
    user = auth.user()
    transactions = Transaction.where('user_id', '=', user.id).get()
    return transactions

用 transactions 變數去存查詢回來的資料,最後 return 出去,Masonite 會很聰明的自動序列化成 JSON 格式丟出去,所以瀏覽器會接收到一份 JSON 的交易紀錄。

JSON 是我們的好朋友,先把前端放一邊,確定 controller actions 都正確之後,下一步再來鼓搗前端的部份。