はじめに
PythonにはDjangoというフルスタックウェブフレームワークがあります. これまでここのブログではマイクロウェブフレームワークであるflaskの記事が多かったのですが, 最近,Djangoを使う機会を得たことで,学ぶ機会ができ,使ってみることにしました.
なお,本記事で扱う環境は以下の通りです
- Python:3.4.2
- Django1.7
学ぶにあたって,まずはここを見て一通り動かしてみました.
解説がよくまとまっており内容もわかりやすいのですが、自分でどんなアプリを作るか決めないまま進めたこともあってか曖昧模糊だったので、シンプルなブログを作って練習してみました。
今回は以下のような仕様のブログの作成しました.
作成するブログ
- 機能
- 記事投稿
- タイトル
- 本文
- 日付
- 記事表示
- 記事投稿
これだけです. 見た目についてもbootstrapなどを使えば簡単にかっこいいウェブアプリがつくれると思いますが,djangoに必要な部分以外外すことで、よりシンプルにして理解しやすくしました..
作成
作成にあたり,まずはdjangoの基本的な使い方を説明します.
djangoのプロジェクト(kuronekoblogとする)をスタートするには
django-admin startproject kuronekoblog
です.
これで基本的なディレクトリが勝手に生成されます.
kuronekoblog/ manage.py kuronekoblog/ __init__.py settings.py urls.py wsgi.py
それぞれのファイルについて説明しましょう.
kuronekoblog/manage.py これはdjangoのアプリを新規作成したり,データベースを扱う,サーバを立ち上げるなどの役割を持つファイルです.
kuronekoblog/kuronekoblog/settings.py 外部ライブラリや日本語ロケールの設定などを行なうファイルです
kuronekoblog/kuronekoblog/urls.py ユーザのアクセスURLによってviews.pyで定義した関数のどれに渡すかを決めるファイル
これらを、まとめると、開発の流れとしては、
settings.pyで日本語ロケール設定をする。
models.pyでデータベースの設計をする。
views.pyにリクエストに応じた関数を書く。
urls.pyにリクエストを受ける時のURLを設定する。
という感じです。
運用の流れとしては
ユーザからリクエストが来たらurls.pyでリクエストの内容に応じてviews.pyのなかに書かれている関数に投げる。
urls.pyよりきたリクエストにしたがってviews.pyでmodels.pyで定義したデータベースを操作したり、templatesで定義したhtmlファイルを呼び出して、ユーザに送信する。
という流れです。
実装
プログラムを組んでいきましょう。
まずは,プロジェクト内にウェブアプリを生成しましょう.
python manage.py startapp blog
これでkuronekoblog/blogというディレクトリが生成されるので全体として次のようになるはずです
kuronekoblog/ manage.py blog/ __init__.py settings.py urls.py wsgi.py kuronekoblog/ __init__.py settings.py urls.py wsgi.py
まずはsettings.pyで日本語設定やblogを扱うように登録をします. 次のように編集してください.
kuronekoblog/settings.py
・・・ INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog', ) ・・・ LANGUAGE_CODE = 'ja' TIME_ZONE = 'Asia/Tokyo' ・・・
ここまでいったら,次はadminページを作ります
まずは次のコマンドを実行してください
python manage.py createsuperuser
実行したら
ユーザID メールアドレス パスワード
が聞かれるので,それぞれ設定してください
次にAdminページで表示させるものについて設定を次のように行なってください.
blog/admin.py
from django.contrib import admin from blog.models import blogdata # Register your models here. class blogdataAdmin(admin.ModelAdmin): list_display = ('id', 'title', 'date',) list_display_links = ('id', 'title',) admin.site.register(blogdata, blogdataAdmin)
次にmodels.pyにてブログのデーターベースを定義します. 今回は,シンプルなブログを作るので次のような情報が扱えるようにしましょう.
- ブログタイトル
- ブログ本文
- ブログの生成日時
では実際に定義していきます.
blog/models.py
from django.db import models from datetime import datetime class blogdata(models.Model): title = models.CharField(max_length=512) text = models.TextField() date = models.DateTimeField(default=datetime.now)
- タイトル(title)はCharFieldで最大512文字まで扱えるようにしました
- 本文(text)はテキストフィールドで好きなように記述できるようにしました
- 投稿日時(date)はDatetimeで現在の日時を渡すようにしました 面白いのはここでは一切SQLを書いてないことです. SQLを書かなくてもこのように直感的な書き方でデータベースが扱えるなんて凄いですね.
では次は,データベースの生成を行ないます
まずは,kuronekoblog自体のデータベースを作りましょう
python manage.py migrate
これで直下にsqliteのファイルが生成されます 次にmodelで定義したblogアプリのデータベースを作ります
python manage.py makemigrations blog
そして反映
python manage.py migrate
ここで一旦ウェブアプリを立ち上げてみましょう
python manage.py runserver
これでlocalhost:8000に立ち上がります. 以下のページにアクセスしてください
先程,定義したAdmin.pyの内容に従って表示されるはずです.
ではviews.pyに処理を書いていきましょう. まずはviews.pyとurls.py動作を確かめるために次のようにしましょう. urls.pyはblog以下に無いはずなので生成してください.
blog/views.py
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def edit(request): return HttpResponse('編集') def show(request): return HttpResponse('読む')
blog/urls.py
#!coding:utf-8 from django.conf.urls import patterns, url from blog import views urlpatterns = patterns('', url(r'^$', views.show, name='show'), url(r'^edit/$', views.edit, name='edit'), )
kuronekoblog/urls.py
from django.conf.urls import patterns, include, url from django.contrib import admin urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)), url(r'^blog/', include('blog.urls', namespace='blog')), )
これでサーバを立ち上げて以下のURLにアクセスしてください
python manage.py runserver
http://localhost:8000/blog/edit
localhost:8000/blogのほうでは「読む」という文字列だけが返ってくるはずです.
localhost:8000/blog/editのほうでは「編集」という文字列だけが返ってくるはずです.
簡単にurls.pyとviews.pyの関係を説明しますと, まずはblog/views.pyの関数では
- edit
- show
の二つの関数をつくりました
次にこれらの関数にリクエストを投げるためにblog/urls.pyに正規表現をつかってリンクさせております.
url(r'^$', views.show, name='show'),
url関数の第一引数がURLのパラメータです.第二引数ではviews.showと書くことで,views.pyの中にあるshow関数にリクエストを投げること. という指定をしてます.第三引数は名前を持たせているだけです(たぶん...).
次にblog/urls.pyをkuronekoblog自体に伝えるために kuronekoblog/urls.pyにblog/urls.pyを登録したわけです.
これで紐付けは完了です.
次はテンプレートまわりを実装しましょう.
テンプレートはjinja2のフォーマットが対応しており,flaskでhtmlを使ったことがある人は馴染み深いはずです.
まずはblog以下にtemplatesを作りましょう.
mkdir blog/templates
この中にbase.htmlというflaskでいうところのlayout.htmlにあたる,各ページ共通部分のヘッダなどを作ります.
touch blog/templates/base.html
base.htmlを編集しましょう.
blog/templates/base.html
<!DOCTYPE html> <html lang="{{ LANGUAGE_CODE|default:"en-us" }}"> <head> <meta charset="UTF-8"> <title>{% block title %}BlogPage{% endblock %}</title> </head> <body> {% block content %} {{ content }} {% endblock %} </body> </html>
次にshow関数で呼ばれるテンプレートを書きます.そのためにディレクトリを次のように追加してください
mkdir blog/templates/blog
ここにテンプレートを作ります.ここではblogshow.htmlというファイルにしましょう.
touch blog/templates/blog/blogshow.html
この中にbase.htmlを継承してブログを表示する部分を書きます. blog/templates/blog/blogshow.html
{% extends "base.html" %} {% block title %}ブログ内容{% endblock title %} {% block content %} {% for blog in blogs %} <h3>日付</h3> {{ blog.date }} <h3>タイトル</h3> {{ blog.title }} <h4>本文</h4> {{ blog.text }} {% endfor %} {% endblock content %}
かなりシンプルですね.日付,タイトル,本文という順で表示されるように想定してます.
では,今つくったtemplatesをviewsに書きましょう. 先程つくったviewsの中身を次のように改造してください
blog/views.py
from django.shortcuts import render_to_response from django.http import HttpResponse from django.template import RequestContext from blog.models import blogdata # Create your views here. def edit(request): return HttpResponse('編集') def show(request): blogs = blogdata.objects.all() return render_to_response('blog/blogshow.html', {'blogs': blogs}, context_instance=RequestContext(request))
flaskではテンプレートを呼ぶときはrender_templatesをつかいましたが,djangoではrender_to_responseを使います. blogsというので,データベースのオブジェクトを受けとって,辞書でテンプレートのhtmlに渡してます.
では実際にAdminを弄ってデータが入ることを確認しましょう. 次のURLにアクセスしてテキトーなブログを作りましょう.
http://localhost:8000/admin/blog/blogdata/
blogdataに追加という箇所をクリックすると編集画面が現われるので書いてみてください.
データベースを管理画面から直感的な操作で弄れるので便利ですね.
追加したら以下のURLにアクセスしてshowがデータベースの内容をひっぱってブログを表示していることを確認してください.
見れたでしょうか.
次は投稿機能を実装します.
基本的にshowを実装した流れは同じなのですが,投稿フォームはdjangoがもともと持っているものを使います. このあたりはさすがフルスタックフレームワークといったところです.
views.pyを開いて次のように編集してください
blog/views.py
#!coding:utf-8 from django.shortcuts import render_to_response from django.http import HttpResponse from django.template import RequestContext from blog.models import blogdata from django.forms import ModelForm class blogform(ModelForm): class Meta: model = blogdata fields = ('title', 'text', 'date', ) def edit(request): blogs = blogdata() form = None if request.method == 'POST': pass else: form = blogform(instance=blogs) return render_to_response('blog/blogedit.html', {'form': form}, context_instance=RequestContext(request)) def show(request): blogs = blogdata.objects.all() return render_to_response('blog/blogshow.html', {'blogs': blogs}, context_instance=RequestContext(request))
さっきと違うのはformの処理とeditの内容を追加したことですね. blogformというクラスでは,modelでは編集するデータベースを指定,fieldsでは投稿画面で編集する内容を記載します.
editの中ではblogdataのインスタンスをblogsで受けとって,それをblogformのクラスに渡したあと,formで受けとっています. そのformをrender_to_responseで処理しているわけです.まずはGET部分の処理だけを書きました.
次はtemplatesです.showと同様にblogedit.htmlをtemplates/blogの中に作って編集します.
blog/templates/blog/blogedit.html
{% extends "base.html" %} {% block title %}投稿{% endblock title %} {% block content %} <form action="{% url 'blog:edit' %}" method="post"> {% csrf_token %} {{ form }} <button type="submit">投稿</button> </form> {% endblock content %}
formアクションの
{% url 'blog:edit' %}
ではblog内のviewsに定義されているeditのformを呼んでいることを示しています.
もう一つ
{% csrf_token %}
というのはこれがないと強制的なリダイレクトとdjangoが誤認識をしてしまうので,その対策に書いてます.
あとは
{{ form }}
でformの内容を呼んでいます.
それでは以下のURLにアクセスして,投稿画面が動いていることを確認してください. レイアウトなどはまったく弄ってないので汚ないと思います(笑)
http://localhost:8000/blog/edit
確認したら,次はviews.pyにpostの処理を追加しましょう.
blog/views.py
#!coding:utf-8 from django.shortcuts import render_to_response, redirect from django.http import HttpResponse from django.template import RequestContext from blog.models import blogdata from django.forms import ModelForm class blogform(ModelForm): class Meta: model = blogdata fields = ('title', 'text', 'date', ) # Create your views here. def edit(request): blogs = blogdata() form = None if request.method == 'POST': form = blogform(request.POST, instance=blogs) if form.is_valid(): blog = form.save(commit=False) blog.save() return redirect('blog:show') pass else: form = blogform(instance=blogs) return render_to_response('blog/blogedit.html', {'form': form}, context_instance=RequestContext(request)) def show(request): blogs = blogdata.objects.all() return render_to_response('blog/blogshow.html', {'blogs': blogs}, context_instance=RequestContext(request))
POSTで受けとった内容をblogformを経由してformで受けとってます.
form.is_valid()
というのは形式が正しいかを判断する部分らしく,バリデーションと呼ばれるようです(知らなかった...).
バリデーションが正しければその投稿内容を保存します.
保存したらredirectでshow関数を呼びだしてブログ内容を表示するようにします.
これでだいたいの処理は書き終わりましたが,
から編集画面のリンクを張りわすれていたので張っておきましょう.
blog/templates/blog/blogedit.html
{% extends "base.html" %} {% block title %}ブログ内容{% endblock title %} {% block content %} <a href="{% url 'blog:edit' %}">投稿画面</a> {% for blog in blogs %} <h3>日付</h3> {{ blog.date }} <h3>タイトル</h3> {{ blog.title }} <h4>本文</h4> {{ blog.text }} {% endfor %} {% endblock content %}
これで完成です.
まとめ
非常に簡易なブログをquitaの記事を参考にしながら作成した.