CakePHP使いがDjangoでサイトを作ってみた 〜ページを作ろう〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
ページ

この記事を三行にまとめると

任意のURLで何かしら出力できるようにしてみたい
Djangoの場合はURLを明示的に設定する
同じURLでGETとPOSTを自動的に振り分けてくれる
前回、DjangoはCakePHPのようなMVCモデルに似ているという話をしました。

MVC的な感覚をつかむ

今回はもうちょい踏み込んで、ビューやテンプレートを使って任意のURLで何かしら出力できるようにしてみたいと思います。がっつりしたページを作るとなるとHTMLとかCSSが絡む話になってしまうので、今回はそういうことはやらずに「https://hogehoge.jp/hello」的なURLでシンプルに「Hello World」を表示するだけのページを作ってみたいと思います。



ファイル構成を確認

まずはファイル構成を確認しときましょう。

/normnois
  ├ /app
  │   ├ /migrations
  │   │   └ __init__.py
  │   │    
  │   ├ __init__.py
  │   ├ admin.py
  │   ├ apps.py
  │   ├ models.py
  │   ├ tests.py
  │   │    
  │   ├ /views
  │   │   ├ __init__.py 
  │   │   └ hello.py
  │   │    
  │   └ /templates
  │       └ hello.html
  │
  ├ /normnois
  │   ├ __init__.py
  │   ├ settings.py
  │   ├ urls.py
  │   └ wsgi.py
  │
  └ manage.py

ビューやテンプレートをCakePHPライクな感じで設置しました。いろいろとファイルがありますが、今回の記事で注目するのはviewsフォルダの下にある「hello.py」とtemplatesフォルダの下にある「hello.html」、それからnormnoisフォルダの下にある「setting.py」と「urls.py」です。一つずつ順番に見ていきましょう。



アプリケーションを有効にする

有効にするという言い方が正しいかは分かりませんが、ビューやモデルを使用できるようにするためにはsetting.pyで任意のアプリケーションを有効にする必要があります。

setting.pyを見るとこんなコードが書かれています。

#setting.py
INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

ここに作成したアプリケーションを追加する。

#setting.py
INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'app',
]

ここで言う「app」はアプリケーションを作成した時のアプリ名なので任意に変わります。今回はappとなっていますが、人によっては「achzionbrucke」とかかもしれない。



URLを作成

アプリケーションを有効にしたら次はURLを設定します。

CakePHPだとデフォルトの設定に従っていればコントローラーやビューファイルを作成するだけでそれに対応したURLにアクセスできるようになりますが、Djangoの場合はURLを明示的に設定する必要があります。

URLの作成はurls.pyで行います。今回は「https://hogehoge.jp/hello」というURLを作りたいので、urls.pyに以下の設定を書きます。

#urls.py
from django.urls import path
from app.views import hello

urlpatterns = [
  path('hello', hello.index.as_view())
]

URLはurlspatternsという変数で設定します。path関数の第一引数の「hello」がURLになります。ここを「helloworld」にすれば「https://hogehoge.jp/helloworld」というURLが有効になりますし「hello/world」にすれば「https://hogehoge.jp/hello/world」というURLが有効になります。

正規表現を使ったりもできるので動的なURLの作成も可能ですが、今回は省略します。

第二引数の「hello.index.as_view()」はViewオブジェクトの作成を行なうメソッドなのですが、それについては次項にて。



ビューを作成

お次はビューの作成です。hello.pyにCakePHPで言うところのコントローラーのような処理を実装します。

説明は後回しにしてまずはコードを書いてみましょう。

#hello.py
from django.shortcuts import render
from django.views.generic import TemplateView

class index(TemplateView) :
  def get(self, request, *args, **kwargs) :
    return render(request, 'hello.html')

こんな感じです。Djangoのビューは大きく分けて関数ベースのビューとクラスベースのビューの二つの書き方があるんですが、今回はクラスベースの方でいきます。何でかってーと、僕がそっちしか使ったことがないからです。関数ベースについて知りたい方はすまんが他で調べてくれい。

クラス名を「index」としているのは、urls.pyの「hello.index.as_view()」でhello.pyのindexクラスのViewオブジェクトを作成しているからです。もしurls.pyで「hello.world.as_view()」としたならばクラス名の方も「world」にする必要があります。

render関数の第二引数で読み込むテンプレートファイルを指定しています。「hello/index.html」とか「hello/world/hoge.html」とかで深い階層のファイルを指定することもできます。CakePHPでもrender関数でテンプレートファイルを指定できますが、あれと同じ感じですね。



テンプレートを作成

最後はhello.htmlです。ここは通常のHTMLの書き方で良いです。

#hello.html
<html>
  <body>
    Hello World
  </body>
</html>



変数を渡す

CakePHPだと「$this->set()」でコントローラーからビューに値を渡すことができます。

//コントローラー
class HelloController() {
  public function index() {
    $this->set('var', 'Hello World');
  }
}

//ビュー
<?php echo $var ?>

これと同じことをDjangoでやるとこんな感じになります。

#ビュー
class index(TemplateView) :
  def get(self, request, *args, **kwargs) :
    context = self.get_context_data(**kwargs)
    context['var'] = 'Hello World'
    return render(request, 'hello.html', context)

#テンプレート
{{var}}

Djangoの場合は変数を二重にかっこで挟んで出力します。AngularJSと似てますかね。リストやディクショナリの場合はピリオドでつなぎます。

#ビュー
class index(TemplateView) :
  def get(self, request, *args, **kwargs) :
    context = self.get_context_data(**kwargs)
    context['var'] = {'hello': 'world'}
    return render(request, 'hello.html', context)

#テンプレート
{{var.hello}}



GETとPOST

クラスベースビューの場合、GETやPOSTは関数で簡単に分けることができます。

#hello.py
class index(TemplateView) :
  def get(self, request, *args, **kwargs) :
    return render(request, 'get.html')
  
  def post(self, request, *args, **kwargs) :
    return render(request, 'post.html')

こう書くだけでGETメソッドの時はget関数を読み込んでget.htmlの内容を表示してくれるし、フォームからデータをPOSTした場合などはpost関数を読み込んでpost.htmlの内容を表示してくれます。






基本の基本はこんなとこですかね。

同じURLでGETとPOSTを自動的に振り分けてくれるってのは個人的には便利だと思います。CakePHPだと「$this->request->is(‘post’)」とかで判定して処理を分けたりしなきゃいけないんだけど、これなら関数単位で分けることができる。AjaxでデータをPOSTする時なんかはこっちの方が楽だなって思います。

それから今回はviewsというフォルダを作ってその中にビューファイルを作成しましたが、サイト全体のページが少ないのであれば、フォルダを作らずに最初からあるviews.pyの中に全部書いちゃっても問題ないです。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください