Djangoの機能構成を理解する
MVT(Model・View・Template)というDjangoの機能構成について理解していきます。
モデル・ビュー・テンプレートの役割
- モデル:アプリで扱うデータを保持し、操作する
- ビュー:ユーザーからのリクエストに応じて、モデル・テンプレートを呼び出す
- テンプレート:データの表示形式を記述する
- ルーティング:リクエストを振り分ける
Djangoでデータベースを操作できるツール
- Djangoシェル:Djangoアプリの環境を有効にしたまま、コマンドで操作
- マイグレーション:データベースの操作を一括実行・取り消し
- 管理サイト: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
管理サイトでパスワードを変更
- 管理サイトにログインする
- 「Users」をクリック
- パスワードを変更したいユーザー名をクリック
- 「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.’の最後にあるリンクをクリック
- 「Change password」フォームに新しいパスワードを入力
- 「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/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('<int:id>', 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('</int:id><int:id>/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へリンク先を指定 -->
削除
</p>
{% endfor %}
<p>
<a href="{% url 'bbs:create' %}">新規</a>
</p>
</body>
</html>
[siteorigin_widget class=”AdWidgetItem”][/siteorigin_widget]
[siteorigin_widget class=”WP_Widget_Search”][/siteorigin_widget]
[siteorigin_widget class=”WP_Widget_Pages”][/siteorigin_widget]
[siteorigin_widget class=”AdWidgetItem”][/siteorigin_widget]
