18b. Django入門2(Djangoの動作の理解)

Djangoの機能構成を理解する

MVT(Model・View・Template)というDjangoの機能構成について理解していきます。

モデル・ビュー・テンプレートの役割

  1. モデル:アプリで扱うデータを保持し、操作する
  2. ビュー:ユーザーからのリクエストに応じて、モデル・テンプレートを呼び出す
  3. テンプレート:データの表示形式を記述する
  4. ルーティング:リクエストを振り分ける

Djangoでデータベースを操作できるツール

  1. Djangoシェル:Djangoアプリの環境を有効にしたまま、コマンドで操作
  2. マイグレーション:データベースの操作を一括実行・取り消し
  3. 管理サイト:Webブラウザで、データベースを操作する

Djangoシェルでデータベースを確認

Djangoシェルを使うと、Djangoアプリの環境を有効にしたまま、Djangoの機能をコマンドで操作できます。

Djangoシェルを起動と終了

$ cd myapp
$ python manage.py shell	# 起動

※ 終了は「ctrl+d」キー

Djangoシェルの主な操作コマンド

# テキストを入力
In[1]: print('Hello Python')
Hello Python

# プリント関数を使わずにデータを書くと、そのまま出力する
In[2]: 'Hello Python'
Out[2]: 'Hello Python'

# テーブルの全てのレコードを出力
In[3]: from bbs.models import Article
In[4]: Article.objects.all()
Out[4]: , , ]>

# 指定idのデータを取り出し、カラムを出力
In[5]: article = Article.objects.get(pk=1)	# プライマリキーが1のデータを取得
In[6]: article.content
Out[6]: 'Hello world'

# データを追加する
In[6]: article = Article(content='Hello Django')
In[7]: article.save()

# データを修正する
In[8]: article = Article.objects.get(pk=1)
In[9]: article.content = 'Good Morning'
In[10]: article.save()

# データを削除する
In[11]: article = Article.objects.get(pk=4)
In[12]: article.delete()

データベースへのマイグレーションを理解する

掲示板アプリケーションのデータベースに投稿者の名前を表すカラムを追加していきます。

マイグレーションとは、データベースの中身を一括して移行したり変更したりする作業です。Djangoのマイグレーション機能では、データベースの定義や変更を一度に行うことができます。マイグレーションの取り消し(ロールバック)もできます。

user_nameカラムを追加

# myproject/bbs/models.py
from django.db import models

class Article(models.Model):					# Articleクラスが記事を操作するためのモデル
    content = models.CharField(max_length=200)
    user_name = models.CharField(max_length=200, null = True)	# user_nameカラムを追加

    def __str__(self):
        return self.content

マイグレーションファイルの作成と実行

$ cd myapp
$ python manage.py makemigrations bbs	# models.pyを読み取って、マイグレーションファイルを作成
Migrations for 'bbs':
  bbs/migrations/0002_article_user_name.py
    - Add field user_name to article

$ python manage.py migrate				# マイグレーションファイルの実行
Operations to perform:
  Apply all migrations: admin, auth, bbs, contenttypes, sessions
Running migrations:
  Applying bbs.0002_article_user_name... OK

管理サイトでパスワードを変更

  1. 管理サイトにログインする
  2. 「Users」をクリック
  3. パスワードを変更したいユーザー名をクリック
  4. 「Change user」-「Password」にある、'Raw passwords are not stored, so there is no way to see this user's password, but you can change the password using this form.'の最後にあるリンクをクリック
  5. 「Change password」フォームに新しいパスワードを入力
  6. 「CHANGE PASSWORD」ボタンをクリック

テンプレートにカラムを追加

モデルに追加したカラムをテンプレートで表示していきます。

index.htmlにカラムを追加

<!-- myapp/bbs/templates/bbs/index.html -->
< !DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>paiza bbs</title>
        <style>body {padding: 10px;}</style>
    </head>
    <body>
        <h1>paiza bbs</h1>
        <p>{{ message }}</p>
        {% for article in articles %}			<!-- articlesから要素を取り出す -->
            <p>
                {{ article.content }},{{ article.user_name }},	<!-- user_nameを追加 -->
                <a href="{% url 'bbs:detail' article.id %}">詳細</a>
            </p>
        {% endfor %}
    </body>
</html>

detail.htmlにカラムを追加

<!-- myapp/bbs/templates/bbs/detail.html -->
< !DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>paiza bbs</title>
        <style>body {padding: 10px;}</style>
    </head>
    <body>
        <h1>paiza bbs</h1>
        <p>{{ message }}</p>
        <!-- ビューから受け取った個別の記事データを表示 -->
        <p>{{ article.content }}, {{ article.user_name }}</p>	<!-- user_nameを追加 -->
        <p><a href="{% url 'bbs:index' %}">一覧</a></p>
    </body>
</html>

Webアプリのデータの流れを理解する

Djangoのルーティングに、新しいルートを追加していきます。

掲示板アプリケーションのルーティング設定

URL呼び出す機能関数
bbs/掲示板:記事の一覧表示index()
bbs/(id)掲示板:記事の個別表示detail()
new記事の作成new()
create記事の投稿create()
bbs/(id)/edit記事の編集edit()
bbs/(id)/update記事の更新update()
bbs/(id)/delete記事の削除delete()

ルートを追加

# myapp/urls.py
from django.urls import include, path
from django.contrib import admin
from django.views.generic import RedirectView		# 追加

urlpatterns = [
    path('bbs/', include('bbs.urls')),
    path('admin/', admin.site.urls),
    path('', RedirectView.as_view(url='/bbs/')),	# 何も指定しない場合、bbsへリダイレクト
]

データベースに書き込む

urls.pyに「create」を追記する

// myapp/bbs/urls.py
from django.urls import path
from . import views

app_name = 'bbs'

urlpatterns = [
    path('', views.index, name='index'),
    path('', views.detail, name='detail'),
    // パスがcreateの場合、viewsのcreate関数を呼び出す
    path('create', views.create, name='create'),
]

views.pyに「create」関数を追加する

// myapp/bbs/views.py
def create(request):
    article = Article(content='Hello BBS', user_name='paiza')	// 固定テキストをセット
    article.save()

    articles = Article.objects.all()
    context = {
        'message': 'Create article',
        'articles': articles,
    }
    return render(request, 'bbs/index.html', context)

新規リンクをテンプレートに追加する

<!-- myapp/bbs/templates/index.html -->
< !DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>paiza bbs</title>
        <style>body {padding: 10px;}</style>
    </head>
    <body>
        <h1>paiza bbs</h1>
        <p>{{ message }}</p>
        {% for article in articles %}
            <p>
                {{ article.content }},{{ article.user_name }},
                <a href="{% url 'bbs:detail' article.id %}">詳細</a>
            </p>
        {% endfor %}
        <p>
	            <!-- ルーティングで指定したcreateをリンク先に指定 -->
            <a href="{% url 'bbs:create' %}">新規</a>
        </p>
    </body>
</html>

データベースから記事を削除

ルートで「delete」にアクセスした時、該当の記事を削除する機能を実装していきます。

urls.pyに「delete」を追記

// myapp/bbs/urls.py
from django.urls import path
from . import views

app_name = 'bbs'

urlpatterns = [
    path('', views.index, name='index'),
    path('', views.detail, name='detail'),
    path('create', views.create, name='create'),
    // idの後がdeleteとなっている場合、viewsのdelete関数を呼び出す
    path('/delete', views.delete, name='delete'),
]

views.pyに、delete関数を追記

// myapp/bbs/views.py
def delete(request, id):
    // 指定のデータを取り出して、データを削除
    article = get_object_or_404(Article, pk=id)
    article.delete()

    articles = Article.objects.all()
    context = {
        'message': 'Delete article ' + str(id),
        'articles': articles,
    }
    return render(request, 'bbs/index.html', context)	// 記事一覧を表示

テンプレートに削除リンクを追加

<!-- myapp/bbs/templates/index.html -->
< !DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'/>
        <title>paiza bbs</title>
        <style>body {padding: 10px;}</style>
    </head>
    <body>
        <h1>paiza bbs</h1>
        <p>{{ message }}</p>
        {% for article in articles %}
            <p>
                {{ article.content }},{{ article.user_name }},
                <a href="{% url 'bbs:detail' article.id %}">詳細</a>,
                <!-- ルーティングで指定したdeleteへリンク先を指定 -->
                <a href="{% url 'bbs:delete' article.id %}">削除</a>
            </p>
        {% endfor %}

        <p>
            <a href="{% url 'bbs:create' %}">新規</a>
        </p>
    </body>
</html>

Webプログラミング入門

タイトルとURLをコピーしました