2023年6月26日  2023年8月5日Python 
サンプルプロジェクトのテンプレート 
 
Djangoで簡単なアプリケーションを開発するためのテンプレート 
アプリケーション概要 
Web画面からデータベースにテキストを登録する 
登録するユーザーを管理する 
 
テキスト中の[projectname] [appname]について 
それぞれ任意のプロジェクト名、アプリケーション名を付ける 
[ ]は視認性のためなのでコマンドや設定ファイルでは不要 
ここではsampleproject、sampleappで作業を行う 
 
 
1.開発環境を構築する 
仮想環境を作成する 
PythonのvenvコマンドでDjango用の仮想環境を作成する 
python -m venv .env_django 
ライブラリをインストールする 
作成したPythonの仮想環境にDjangoのライブラリをインストールする 
pip install django 
 
2.プロジェクトを作成する 
django-admin コマンドでプロジェクトを作成する 
django-admin startproject [projectname] 
Djangoのプロジェクトを作成する 
仮想環境に作成するのでvenvが起動している状態で実行する 
 
プロジェクト初期のファイル構成 
[projectname] フォルダ
__init__.py 
asgi.py 
settings.py 
urls.py 
wsgi.py 
  
manage.py 
 
初期の雛形ファイルを用いてローカルサーバを起動する 
コマンドでローカルサーバを起動する 
python manage.py runserver 
プロジェクト設定を変更する 
[projectname]/settings.py 
変更箇所 
変更前 
変更後 
 
 
LANGUAGE_CODE 
en-us 
ja 
 
TIME_ZONE 
UTC 
Asia/Tokyo 
 
 
 
3.データベースをセットアップする 
テーブルを作成する 
コマンドでマイグレーションを実行しテーブルを作成する 
python manage.py migrate 
実行結果 
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  (中略)
  Applying sessions.0001_initial... OK 
 
4.アプリケーションを作成する 
機能の最小単位となるアプリケーションを作成する 
プロジェクトの中にアプリケーションの雛形を作成する 
python manage.py startapp [appname] 
この時点でのファイル構成 
[appname] フォルダ 
[projectname] フォルダ 
db.sqlite3 
manage.py 
 
プロジェクト設定を変更する 
[projectname]/settings.py 
'[appname].apps.[Appname]Config',  の形式でアプリケーション設定を追加する 
 
変更箇所 
変更前 
変更後 
 
 
INSTALLED_APPS 
(末尾に追加する) 
'sampleapp.apps.SampleappConfig', 
 
 
 
5.トップページを表示する 
ビュー関数を定義する 
[appname]/views.py 
from django.http import HttpResponse
def top(request):
    return HttpResponse(b'Hello World from app/views.py ')
 
ルーティングを設定する 
[projectname]/urls.py 
from django.contrib import admin
from django.urls import path
from sampleapp.views import top
urlpatterns = [
    path('', top, name='top'),
    path('admin/', admin.site.urls),
]
 
django.urls.path の引数について 
HTTPリクエストパス
ここでは '/' へのアクセスに対してtop関数を呼び出す設定 
先頭の / は省略するため空白を指定している 
  
ビュー関数(views.py のtop関数) 
URLの逆引き時に利用するキーワード引数 
 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
追加のルーティング設定をする 
以下のページを作成する想定でルーティングを設定しておく 
ページ 
内容 
 
 
top 
一覧画面 
 
sample_new 
登録画面 
 
sample_edit 
編集画面 
 
sample_detail 
詳細画面 
 
 
[appname]/views.py 
from django.http import HttpResponse
def top(request):
    return HttpResponse(b'Hello World from app/views.py ')
def sample_new(request):
    return HttpResponse('登録画面')
def sample_edit(request, sample_id):
    return HttpResponse('編集画面')
def sample_detail(request, sample_id):
    return HttpResponse('詳細画面')
 
[appname]/urls.py を新規作成する 
from django.urls import path
from sampleapp import views
urlpatterns = [
    path('new/', views.sample_new, name='sample_new'),
    path('/', views.sample_detail, name='sample_detail'),
    path('/edit/', views.sample_edit, name='sample_edit'),
]
   
[projectname]/urls.py 
from django.contrib import admin
from django.urls import path, include
from sampleapp.views import top
urlpatterns = [
    path('', top, name='top'),
    path('sampleapp/', include('sampleapp.urls')),
    path('admin/', admin.site.urls),
]
 
 
6.データベースと連携する 
モデルを定義する 
[appname]/models.py 
from django.conf import settings
from django.db import models
class Sample(models.Model):
    title = models.CharField('タイトル', max_length=128)
    text = models.TextField('テキスト', blank=True)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='登録者', on_delete=models.CASCADE)
    created_at = models.DateTimeField('登録日', auto_now_add=True)
    updated_at = models.DateTimeField('更新日', auto_now=True)
    def __str__(self):
        return self.title
 
データベースをマイグレーションする 
マイグレーションを作成する 
python manage.py makemigrations 
実行結果 
Migrations for 'sampleapp':
sampleapp\migrationsMigrations for 'sampleapp':
sampleapp\migrations\0001_initial.py
  - Create model Sample 01_initial.py
  - Create model Sample 
マイグレーションをテーブルに反映する 
python manage.py migrate 
実行結果 
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sampleapp, sessions
Running migrations:
  Applying sampleapp.0001_initial... OK 
 
7.管理画面を利用する 
管理画面からのテーブル操作を有効にする 
[appname]/admin.py 
from django.contrib import admin
from sampleapp.models import Sample
admin.site.register(Sample)
 
ユーザを作成する 
管理者となるadmin権限を持つユーザを作成する 
python manage.py createsuperuser 
実行結果 
Username (leave blank to use 'username'): admin
Email address: admin@sample.com
Password:
Password (again):
Superuser created successfully. 
管理画面にログインする 
ローカルサーバを起動する 
python manage.py runserver 
 
8.データベースを操作する 
Pythonのシェルからデータベースを操作する 
シェルを起動する 
python manage.py shell 
データを取得する 
作成したユーザ情報を取得する 
from django.contrib.auth.models import User
users = User.objects.all()
users
 
実行結果 
<QuerySet [<User: admin>]> 
IDを指定してユーザデータを取得する 
User.objects.get(id=1)
 
実行結果 
<User: admin> 
ユーザ名を指定してユーザデータを取得する 
User.objects.get(username='admin')
 
実行結果 
<User: admin> 
データを作成する 
モデル定義に合わせてデータを作成する 
from sampleapp.models import Sample
admin_user = User.objects.get(id=1)
sample = Sample(title='コマンドからのテスト入力',
                text='コマンドからのテスト入力です',
                created_by=admin_user)
 
作成された項目を表示する 
sample.title
 
実行結果 
'コマンドからのテスト入力' 
自動採番項目はsaveメソッドを実行しないと反映されない 
sample.id
 
実行結果 
>>>(表示なし) 
saveを実行して再度確認する 
sample.save()
sample.id
 
実行結果 
1 
データを更新する 
id=1のtitle属性を更新する 
sample = Sample.objects.get(id=1)
sample.title = 'コマンドからの更新テスト'
sample.save()
Sample.objects.all()
 
実行結果 
<QuerySet [<Sample: コマンドからの更新テスト>]> 
データを削除する 
deleteメソッドでデータを削除する 
sample.delete()
 
実行結果 
(1, {'sampleapp.Sample': 1}) 
削除の確認をする 
Sample.objects.all()
 
実行結果 
<QuerySet []> 
 
9.トップページをHTMLファイルで表示する 
HTMLファイルを作成する 
[appname]フォルダ配下にHTMLファイル用のフォルダを作成する 
[appname]/templates/[appname] 
 
sampleapp/templates/sampleapp/top.html 
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappのトップページ</title>
</head>
<body>
  <p>Hello World from sampleapp/templates/sampleapp/top.html</p>
</body>
</html> 
ルーティングの設定をする 
[appname]/views.py 
from django.http import HttpResponse
from django.shortcuts import render
def top(request):
    return render(request, 'sampleapp/top.html')
def sample_new(request):
    return HttpResponse('登録画面')
def sample_edit(request, sample_id):
    return HttpResponse('編集画面')
def sample_detail(request, sample_id):
    return HttpResponse('詳細画面')
 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
 
10.トップページにデータベースの情報を表示する 
ビュー関数を設定する 
[appname]/views.py 
from django.http import HttpResponse
from django.shortcuts import render
from sampleapp.models import Sample
def top(request):
    sampleapp = Sample.objects.all()
    context = {'sampleapp': sampleapp}
    return render(request, 'sampleapp/top.html', context)
def sample_new(request):
    return HttpResponse('登録画面')
def sample_edit(request, sample_id):
    return HttpResponse('編集画面')
def sample_detail(request, sample_id):
    return HttpResponse('詳細画面')
 
top.htmlファイルを編集する 
[appname]/templates/[appname]/top.html 
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappのトップページ</title>
</head>
<body>
  <h1>Django sampleproject のトップページ</h1>
  <h2>DB登録情報</h2>
  {% if sampleapp %}
  <table class="table">
    <thead>
      <tr>
        <th>登録者</th>
        <th>登録日</th>
        <th>タイトル</th>
      </tr>
    </thead>
    <tbody>
      {% for sample in sampleapp %}
      <tr>
        <th>{{ sample.created_by.username }}</th>
        <th>{{ sample.created_at }}</th>
        <th><a href="{% url 'sample_detail' sample.id %}">{{ sample.title }}</a></th>
      </tr>
      {% endfor %}
    </tbody>
  </table>
  {% else %}
  <p>登録情報がありません</p>
  {% endif %}
</body>
</html> 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
 
11.詳細画面を表示する 
ビュー関数を設定する 
[appname]/views.py 
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from sampleapp.models import Sample
def top(request):
    sampleapp = Sample.objects.all()
    context = {'sampleapp': sampleapp}
    return render(request, 'sampleapp/top.html', context)
def sample_new(request):
    return HttpResponse('登録画面')
def sample_edit(request, sample_id):
    return HttpResponse('編集画面')
def sample_detail(request, sample_id):
    sample = get_object_or_404(Sample, pk=sample_id)
    return render(request, 'sampleapp/sample_detail.html', {'sample': sample})
 
htmlファイルを作成する 
[appname]/templates/[appname]/sample_detail.html 
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappの詳細画面</title>
</head>
<body>
  <div>
    <h1>{{ sample.title }} by {{ sample.created_by.username }}</h1>
    <h2>登録日: {{ sample.created_at }}</h2>
    <h2>{{ sample.text }}</h2>
  </div>
</body>
</html> 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
 
12.登録・編集画面を表示する 
HTML検証用のフォームファイルを作成する 
[appname]/forms.py 
from django import forms
from sampleapp.models import Sample
class SampleForm(forms.ModelForm):
    class Meta:
        model = Sample
        fields = ('title', 'text')
 
ビュー関数を設定する 
[appname]/views.py 
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden
from django.shortcuts import render, redirect, get_object_or_404
from sampleapp.forms import SampleForm
from sampleapp.models import Sample
def top(request):
    sampleapp = Sample.objects.all()
    context = {'sampleapp': sampleapp}
    return render(request, 'sampleapp/top.html', context)
@login_required
def sample_new(request):
    if request.method == 'POST':
        form = SampleForm(request.POST)
        if form.is_valid():
            sample = form.save(commit=False)
            sample.created_by = request.user
            sample.save()
            return redirect(sample_detail, sample_id=sample.pk)
    else:
        form = SampleForm()
    return render(request, 'sampleapp/sample_new.html', {'form': form})
@login_required
def sample_edit(request, sample_id):
    sample = get_object_or_404(Sample, pk=sample_id)
    if sample.created_by_id != request.user.id:
        return HttpResponseForbidden("このテキストの編集は許可されていません。")
    if request.method == "POST":
        form = SampleForm(request.POST, instance=sample)
        if form.is_valid():
            form.save()
            return redirect('sample_detail', sample_id=sample_id)
    else:
        form = SampleForm(instance=sample)
    return render(request, 'sampleapp/sample_edit.html', {'form': form})
def sample_detail(request, sample_id):
    sample = get_object_or_404(Sample, pk=sample_id)
    return render(request, 'sampleapp/sample_detail.html', {'sample': sample})
 
[appname]/templates/[appname]/sample_new.html 
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappの登録画面</title>
</head>
<body>
  <h1>登録フォーム</h1>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">登録</button>
  </form>
</body>
</html> 
[appname]/templates/[appname]/sample_edit.html 
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappの編集画面</title>
</head>
<body>
  <h1>編集フォーム</h1>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">保存</button>
  </form>
</body>
</html> 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
 
13.見た目を整える 
CSSを適用する 
Bootstrapをインストールする 
pip install django-bootstrap5 
プロジェクト設定を変更する 
[projectname]/settings.py 
変更箇所 
変更前 
変更後 
 
 
INSTALLED_APPS 
(末尾に追加する) 
'django_bootstrap5', 
 
TEMPLATES 
[], 
[BASE_DIR / 'templates'], 
 
 
HTMLファイルを変更する 
[appname]/templates/[appname]/top.html 
{% load django_bootstrap5 %}
<html>
<head>
  <meta charset="utf-8">
  <title>sampleappのトップページ</title>
  {% bootstrap_css %}
  {% bootstrap_javascript %}
</head>
<body>
  <nav class="navbar-expand flex-md-row navbar-dark bg-dark">
    <div class="container justify-content-between">
      <a href="/" class="navbar-brand">sampleapp</a>
    </div>
  </nav>
  <main>
    <div class="container">
      <div class="welcome">
        <h1>Django sampleproject のページ</h1>
        <a class="btn btn-primary" href="{% url 'sample_new' %}">テキストの新規登録</a>
      </div>
      <h3>DB登録情報</h3>
      {% if sampleapp %}
      <table class="table">
        <thead>
          <tr>
            <th>登録者</th>
            <th>登録日</th>
            <th>タイトル</th>
          </tr>
        </thead>
        <tbody>
          {% for sample in sampleapp %}
          <tr>
            <th>{{ sample.created_by.username }}</th>
            <th>{{ sample.created_at }}</th>
            <th><a href="{% url 'sample_detail' sample.id %}">{{ sample.title }}</a></th>
          </tr>
          {% endfor %}
        </tbody>
      </table>
      {% else %}
      <p>登録情報がありません</p>
      {% endif %}
    </div>
  </main>
</body>
</html> 
CSSファイルを適用する 
[appname]/static/[appname]/css/style.css 
main {
  padding: 2rem 0;
}
.welcome {
  padding: 3rem 0;
  margin-bottom: 2rem;
  background-color: #eee;
  align-items: center;
  display: flex;
  flex-direction: column;
}
.snippet-date {
  margin-bottom: 1rem;
}
.source-code>.highlight {
  padding: 1rem;
  margin-bottom: 1rem;
} 
14.HTMLの部品を共通化する 
ベースとなるHTMLファイルを作成する 
[projectname]/templates/base.html 
templates フォルダは [appname] [projectname] と同じ階層 
 
{% load static %}
{% load django_bootstrap5 %}
<html>
<head>
  <meta charset="utf-8">
  <title>sampleapp</title>
  {% bootstrap_css %}
  {% bootstrap_javascript %}
  <link rel="stylesheet" href="{% static 'sampleapp/css/style.css' %}">
  {% block extraheader %}{% endblock %}
</head>
<body>
  <nav class="navbar navbar-expand flex-md-row navbar-dark bg-dark">
    <div class="container justify-content-between">
      <a href="/" class="navbar-brand">sampleapp</a>
    </div>
  </nav>
  <main>
    <div class="container">
      {% block main %}{% endblock %}
    </div>
  </main>
</body>
</html> 
base.htmlを継承するようにHTMLファイルを変更する 
[appname]/templates/[appname]/top.html 
{% extends "base.html" %}
{% block main %}
<div class="welcome">
  <h1 class="title">Django sampleproject のページ</h1>
  <a class="btn btn-primary" href="{% url 'sample_new' %}">テキストの新規登録</a>
</div>
<h3>DB登録情報</h3>
{% if sampleapp %}
<table class="table">
  <thead>
    <tr>
      <th>登録者</th>
      <th>登録日</th>
      <th>タイトル</th>
    </tr>
  </thead>
  <tbody>
    {% for sample in sampleapp %}
    <tr>
      <th>{{ sample.created_by.username }}</th>
      <th>{{ sample.created_at }}</th>
      <th><a href="{% url 'sample_detail' sample.id %}">{{ sample.title }}</a></th>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% else %}
<p>登録情報がありません</p>
{% endif %}
{% endblock %} 
[appname]/templates/[appname]/sample_new.html 
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block main %}
<h2>sampleappの登録画面</h2>
<form method="post">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% bootstrap_button button_type="submit" content="登録" %}
</form>
{% endblock %} 
[appname]/templates/[appname]/sample_edit.html 
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block main %}
<h2>sampleappの編集画面</h2>
<form method="post">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% bootstrap_button button_type="submit" content="保存" %}
</form>
{% endblock %} 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
ログイン状態で以下の画面にアクセスし見た目を確認する
 
 
 
15.アカウント管理機能を実装する 
アプリケーションを作成する 
コマンドの実行 
python manage.py startapp accounts 
ルーティングの設定をする 
[projectname]/settings.py 
変更箇所 
変更前 
変更後 
 
 
INSTALLED_APPS 
(末尾に追加する) 
'accounts.apps.AccountsConfig', 
 
 
accounts/urls.py を新規作成する 
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
urlpatterns = [
    path('login/', LoginView.as_view(
        redirect_authenticated_user=True,
        template_name='accounts/login.html'
    ), name='login'),
    path('logout/', LogoutView.as_view(), name='logout'),
]
 
Django提供のクラスベースビュー(LoginView, LogoutView)を利用してビューの実装を省略する 
 
[projectname]/urls.py 
from django.contrib import admin
from django.urls import path, include
from sampleapp.views import top
urlpatterns = [
    path('', top, name='top'),
    path('sampleapp/', include('sampleapp.urls')),
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')),
]
 
ログイン用のページを作成する 
accounts/templates/accounts/login.html を新規作成する 
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block main %}
<h2>ログイン</h2>
<form method="post">
  {% csrf_token %}
  <input type="hidden" name="next" value="{{ next }}" />
  {% bootstrap_form form %}
  {% bootstrap_button button_type="submit" content="ログイン" %}
</form>
{% endblock %} 
ログイン・ログアウト用のリンクを追加する 
[projectname]/templates/base.html 
{% load static %}
{% load django_bootstrap5 %}
<html>
<head>
  <meta charset="utf-8">
  <title>sampleapp</title>
  {% bootstrap_css %}
  {% bootstrap_javascript %}
  <link rel="stylesheet" href="{% static 'sampleapp/css/style.css' %}">
  {% block extraheader %}{% endblock %}
</head>
<body>
  <nav class="navbar navbar-expand flex-md-row navbar-dark bg-dark">
    <div class="container justify-content-between">
      <a href="/" class="navbar-brand">sampleapp</a>
      <ul class="navbar-nav mr-md-2">
        {% if user.is_authenticated %}
        <li class="nav-item"><a class="nav-link" href="{% url 'logout' %}">ログアウト</a></li>
        {% else %}
        <li class="nav-item"><a class="nav-link" href="{% url 'login' %}">ログイン</a></li>
        {% endif %}
      </ul>
    </div>
  </nav>
  <main>
    <div class="container">
      {% block main %}{% endblock %}
    </div>
  </main>
</body>
</html> 
プロジェクト設定を変更する 
[projectname]/settings.py 
# ユーザー認証
#
LOGIN_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver 
 
16.ユーザー登録機能の実装 
パスを設定する 
accounts/urls.py 
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
from django.views.generic import CreateView
urlpatterns = [
    path('signup/', CreateView.as_view(
        template_name='accounts/signup.html',
        form_class=UserCreationForm,
        success_url='/',
    ), name='signup'),
    path('login/', LoginView.as_view(
        redirect_authenticated_user=True,
        template_name='accounts/login.html'
    ), name='login'),
    path('logout/', LogoutView.as_view(), name='logout'),
]
 
ユーザー登録用のページを作成する 
accounts/templates/accounts/signup.html を新規作成する 
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block main %}
<h2>ユーザー登録</h2>
<form method="post">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% bootstrap_button button_type="submit" content="登録" %}
</form>
{% endblock %} 
ユーザー登録用のリンクを追加する 
[projectname]/templates/base.html 
{% load static %}
{% load django_bootstrap5 %}
<html>
<head>
  <meta charset="utf-8">
  <title>sampleapp</title>
  {% bootstrap_css %}
  {% bootstrap_javascript %}
  <link rel="stylesheet" href="{% static 'sampleapp/css/style.css' %}">
  {% block extraheader %}{% endblock %}
</head>
<body>
  <nav class="navbar navbar-expand flex-md-row navbar-dark bg-dark">
    <div class="container justify-content-between">
      <a href="/" class="navbar-brand">sampleapp</a>
      <ul class="navbar-nav mr-md-2">
        {% if user.is_authenticated %}
        <li class="nav-item"><a class="nav-link" href="{% url 'logout' %}">ログアウト</a></li>
        {% else %}
        <li class="nav-item"><a class="nav-link" href="{% url 'login' %}">ログイン</a></li>
        <li class="nav-item"><a class="nav-link" href="{% url 'signup' %}">ユーザー登録</a></li>
        {% endif %}
      </ul>
    </div>
  </nav>
  <main>
    <div class="container">
      {% block main %}{% endblock %}
    </div>
  </main>
</body>
</html> 
ブラウザから確認する 
ローカルサーバを起動する 
python manage.py runserver