Top / Programming / Python / Django TIPS / 簡易掲示板を作成する

簡易掲示板を作成する

Djangoの簡単な練習として、掲示板を作成します。 Python2.5とDjango1.0.2を使用しました。

プロジェクトの作成

プロジェクトを作成するフォルダでコマンドを実行します。

django-admin startproject example

exampleディレクトリにファイル一式が生成されます。

example/
├__init__.py
├manage.py
├settins.py
└urls.py

アプリケーションの作成

Djangoプロジェクトのディレクトリ(exampleディレクトリ)でコマンドを実行します。

cd example
python manage.py startapp bbs

example/bbsディレクトリにファイル一式が生成されます。

example/ <-このディレクトリでコマンドを実行する
├__init__.py
├manage.py
├settins.py
├urls.py
└bbs/
  ├__init__.py
  ├models.py
  └views.py

INSTALLED_APPSにアプリケーションを追加します。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'bbs', #<-追加する
)

データベースの設定

settings.pyを編集して、データベースの設定を行います。
SQLite3を使用します。

example/
├__init__.py
├manage.py
├settins.py <-このファイルを編集
├urls.py
└bbs/
  ├__init__.py
  ├models.py
  └views.py

settings.pyのDATABASE_ENGINEとDATABASE_NAMEを編集します。

import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = os.path.join(BASE_DIR, 'data.db')
#DATABASE_ENGINE = ''           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
#DATABASE_NAME = ''             # Or path to database file if using sqlite3.

ついでに、TIME_ZONEとLANGUAGE_CODEも編集しましょう。

#TIME_ZONE = 'America/Chicago'
TIME_ZONE  = 'Japan/Tokyo'

#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja-jp'

モデルの作成

モデルを作成します。

bbs/models.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
└bbs/
  ├__init__.py
  ├models.py <-このファイルを編集
  └views.py

ファイルの文字コードはUTF-8にします。

# -*- coding: utf-8 -*-
from django.db import models
from datetime import datetime

class Thread(models.Model):
    #タイトル
    title = models.CharField(u'タイトル', max_length=200, blank=False)
    #メッセージ
    message = models.TextField(u'メッセージ', blank=False)
    #登録日時
    pub_date = models.DateTimeField(u'登録日時', auto_now_add=True, editable=False)

    class Meta:
        verbose_name = u'スレッド'

    def __unicode__(self):
        return self.message

class Comment(models.Model):
    #スレッド
    thread = models.ForeignKey(Thread, verbose_name=u'スレッド')
    #メッセージ
    message = models.CharField(u'メッセージ', max_length=200, blank=False)
    #登録日時
    pub_date = models.DateTimeField(u'登録日時', auto_now_add=True, editable=False)

    class Meta:
        verbose_name = u'コメント'

    def __unicode__(self):
        return self.message

スレッドとコメントは「1対多」の関連です。

Django管理サイト(Adminサイト)の設定

モデルの編集を行うDjango管理サイト(Adminサイト)を有効化します。

settings.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py <-このファイルを編集
├urls.py
└bbs/
  ├__init__.py
  ├models.py
  └views.py

INSTALLED_APPSに'django.contrib.admin'を追加します。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'bbs',
    'django.contrib.admin', #<-追加する
)

urls.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py <-このファイルを編集
└bbs/
  ├__init__.py
  ├models.py
  └views.py

Django管理サイト(Adminサイト)のコメントを解除します。

from django.conf.urls.defaults import *

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
)

データベースのテーブルの作成

Djangoプロジェクトのディレクトリ(exampleディレクトリ)で次のコマンドを実行します。

python manage.py syncdb

Djangoの認証システムのスーパーバイザを登録するか、聞いてきます。

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no):

後から登録することもできますが、ここで登録しておきます。 ユーザー名、メールアドレス、パスワードを入力します。 Django管理サイトのログイン

Djangoプロジェクトのディレクトリ(exampleディレクトリ)で次のコマンドを実行し、テスト用のWebサーバを起動します。

python manage.py runserver

Webブラウザでhttp://127.0.0.1:8000/admin/にアクセスします。

Django管理サイトのログイン画面が表示されたら、先ほど入力したユーザ名とパスワードを入力してログインします。

Django管理サイトにモデルを登録

Django管理サイトにモデルを登録します。

bbs/admin.pyを作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
└bbs/
  ├__init__.py
  ├admin.py <-このファイルを作成
  ├models.py
  └views.py

次のコードを入力します。

# -*- coding: utf-8 -*-
from django.contrib import admin
from example.bbs.models import Thread, Comment

class CommentInline(admin.StackedInline):
    model = Comment
    extra = 1

class ThreadAdmin(admin.ModelAdmin):
    inlines = [CommentInline]

admin.site.register(Thread, ThreadAdmin)

再びWebブラウザでDjango管理サイト(http://127.0.0.1:8000/admin/)にアクセスします。

Bbsの項目が追加されて、スレッドを編集することができるようになっています。

試しにスレッドとコメントの追加や編集、削除を行ってください。

テンプレートファイルの設置ディレクトリの設定

画面を作り込む前に、テンプレートファイルの設置ディレクトリを設定します。

settings.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py <-このファイルを編集
├urls.py
└bbs/
  ├__init__.py
  ├admin.py
  ├models.py
  └views.py

TEMPLATE_DIRSにテンプレートファイルの設置ディレクトリを設定します。

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates')
)

定数BASE_DIRはデータベースの設定の時に作成しました。

テンプレートファイルの設置ディレクトリを作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/ <-ディレクトリを作成
  └bbs/ <-ディレクトリを作成

共通テンプレートの作成

テンプレートの共通部分を作成します。

templates/base.htmlを作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html <-このファイルを作成
  └bbs/

templates/base.htmlを編集します。

<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

templates/base.htmlは、これから作成するテンプレートファイルの共通部分になります。

スレッドの一覧表示

スレッドを一覧表示する画面を作成します。

urls.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py <-このファイルを編集
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/

汎用ビューを使用して作成します。
データの一覧表示のようなよくある処理は、汎用ビューを使用することで手間を省くことができます。

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
from example.bbs.models import Thread

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    #Django管理サイト(Adminサイト)
    (r'^admin/(.*)', admin.site.root),
    #スレッド一覧のページ
    (r'^(?P<page>[0-9]+)/$',
     'django.views.generic.list_detail.object_list',
     {'queryset': Thread.objects.all().order_by('-id'),
      'paginate_by': 5,
      'allow_empty': True}),
    #トップページ。スレッド一覧のページにリダイレクトする
    (r'^$', 'django.views.generic.simple.redirect_to', {'url': '/1/'}),
)

スレッドの一覧表示に関する設定は次の部分です。

#スレッド一覧のページ
(r'^(?P<page>[0-9]+)/$',
 'django.views.generic.list_detail.object_list',
 {'queryset': Thread.objects.all().order_by('-id'),
  'paginate_by': 5,
  'allow_empty': True}),

スレッド一覧ページのURLは、http://〜/ページ番号/になります。
1ページに表示するスレッドは5件にしました。

テンプレートファイルは'bbs/thread_list.html'を使用します。

また、トップページにアクセスしたときに、スレッド一覧ページにリダイレクトする設定も行ってます。

#トップページ。スレッド一覧のページにリダイレクトする
(r'^$', 'django.views.generic.simple.redirect_to', {'url': '/1/'}),

http://〜/にアクセスするとhttp://〜/1/にリダイレクトします。

テンプレートファイル(templates/bbs/thread_list.html)を作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    └thread_list.html <-このファイルを作成

templates/bbs/thread_list.htmlを編集します。

{% extends 'base.html' %}

{% block title %}
スレッド一覧
{% endblock %}

{% block content %}
<ul>
{% for thread in object_list %}
  <li>
    <a href="/thread/{{ thread.id }}/">{{ thread.message }}</a>
    ({{ thread.pub_date|date:"Y年m月d日h時i分s秒" }})
  </li>
{% endfor %}
</ul>

<p><a href="/thread/new/">スレッドの新規作成</a></p>

<p>{{ page }} / {{ pages }}</p>

{% if has_previous %}
<p><a href="/{{ previous }}">前のページ</a></p>
{% endif %}

{% if has_next %}
<p><a href="/{{ next }}">次のページ</a></p>
{% endif %}

{% endblock %}

テンプレートファイルの共通部分であるtemplates/base.htmlを継承します。 テンプレートファイル内で使用している変数(object_listやpageなど)は、汎用ビューの機能によって、自動的に作成されています。

スレッドの新規作成ページのURLはhttp://〜/thread/new/としました。

Webブラウザでhttp://127.0.0.1:8000/にアクセスします。
http://127.0.0.1:8000/にアクセスすると、http://127.0.0.1:8000/1/にリダイレクトします。
登録されているスレッドが一覧表示されます。

スレッドの新規作成

スレッドの新規作成ページを作成します。

urls.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py <-このファイルを編集
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    └thread_list.html

ここでも汎用ビューを使用して作成します。

…
urlpatterns = patterns('',
…
    #スレッドの新規作成ページ
    (r'^thread/new/$',
     'django.views.generic.create_update.create_object',
     {'model': Thread,
      'post_save_redirect': ''}),
)

post_save_redirectで、スレッドを作成した後はトップページ(http://〜/)にリダイレクトするように設定しています。

テンプレートファイル(templates/bbs/thread_form.html.html)を作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    ├thread_form.html <-このファイルを作成
    └thread_list.html

templates/bbs/thread_form.htmlを編集します。

{% extends 'base.html' %}
{% block title %}
スレッドの新規作成
{% endblock %}

{% block content %}
<h1>スレッドの新規作成</h1>
<form action="./" method="post">
<table>
{{ form }}
</table>
<input type="submit" value="作成する" />
</form>
<p><a href="/">トップページに戻る</a></p>
{% endblock %}

以上で、スレッドの新規作成ページが完成しました。

Webブラウザでhttp://127.0.0.1:8000/thread/new/にアクセスして、スレッドを作成できることを確認します。

スレッドページの作成

スレッドページを作成します。

汎用ビューに頼っているとコードをほとんど書かなくなってしまいますので、 汎用ビューを使わずに作成しましょう。

urls.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py <-このファイルを編集
├bbs
│├__init__.py
│├admin.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    └thread_list.html

http://〜/thread/スレッドID/にアクセスするとスレッドページを表示するようにします。

…
urlpatterns = patterns('',
…
    #スレッドの詳細ページ
    (r'^thread/(?P<thread_id>\d+)/$', 'bbs.views.thread_detail'),
)

bbs/forms.pyを作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├forms.py <-このファイルを作成
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    ├thread_form.html
    └thread_list.html

bbs/forms.pyを編集します。

# -*- coding: utf-8 -*-
from django.forms import ModelForm
from example.bbs.models import Comment

class CommentForm(ModelForm):
    class Meta:
        model = Comment
        exclude = ('thread', )

CommentFormはコメントを登録するフォームです。

bbs/views.pyを編集します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├forms.py
│├models.py
│└views.py <-このファイルを編集
└templates/
  ├base.html
  └bbs/
    ├thread_form.html
    └thread_list.html

スレッドとスレッドのコメントを表示します。
また、POSTでアクセスした場合はコメントを登録します。

# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response, get_object_or_404
from example.bbs.models import Thread, Comment
from example.bbs.forms import CommentForm

def thread_detail(request, thread_id):
    '''
    指定したスレッドを表示する。
    @param thread_id: スレッドID
    '''
    #表示するスレッド
    thread = get_object_or_404(Thread, pk=thread_id)
    #コメントの登録処理
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            #コメントを登録
            comment = form.save(commit = False)
            comment.thread = thread
            comment.save()
            form = CommentForm() #フォームの初期化
    else:
        form = CommentForm()
    #スレッドのコメント
    comment_list = thread.comment_set.all().order_by('id')
    return render_to_response('bbs/thread_detail.html',
                              {'thread': thread,
                               'comment_list': comment_list,
                               'form': form})

templates/bbs/thread_detail.htmlを作成します。

example/
├__init__.py
├manage.py
├settins.py
├urls.py
├bbs
│├__init__.py
│├admin.py
│├forms.py
│├models.py
│└views.py
└templates/
  ├base.html
  └bbs/
    ├thread_detail.html <-このファイルを作成
    ├thread_form.html
    └thread_list.html

templates/bbs/thread_detail.htmlを編集します。

{% extends 'base.html' %}

{% block title %}
{{ thread.title }}
{% endblock %}

{% block content %}
<h1>{{ thread.title }}</h1>
<p>
  {{ thread.message }}<br />
  ({{ thread.pub_date|date:"Y年m月d日h時i分s秒" }})
</p>
<hr />
<ul>
{% for comment in comment_list %}
  <li>
    {{ comment.message }}<br />
    ({{ comment.pub_date|date:"Y年m月d日h時i分s秒" }})
  </li>
{% endfor %}
</ul>
<hr />
<form action="./" method="post">
{{ form.as_p }}
<input type="submit" value="コメントを投稿する" />
</form>
<p><a href="/">トップページに戻る</a></p>
{% endblock %}

スレッドページができました。

Webブラウザでアクセスして、動作を確認してください。

以上で完成です。

更新履歴