djangoを殆ど触ったことがない為、参考urlの内容を写経してみました
目次
- 参考url
- python仮想環境作成と、djangoのインストール
- django プロジェクトの作成
- 付属サーバによる接続確認
- 簡易アプリ作成 - その1. VIEW
- 簡易アプリ作成 - その2. MODEL
- 付属する管理ツール
- HTMLテンプレート
- DB変更 - CRUD
- 静的ファイル
参考url
python仮想環境作成と、djangoのインストール
$ cat /etc/redhat-release Red Hat Enterprise Linux release 9.1 (Plow) $ which python ~/.pyenv/shims/python $ python --version Python 3.9.14 $ pwd /home/end0tknr/proj $ python -m venv django $ source ./bin/activate $ pip install django : Successfully installed asgiref-3.6.0 django-4.1.7 sqlparse-0.4.3
django プロジェクトの作成
設定dir名がプロジェクト名となる為、一旦、 config という名でプロジェクト作成し、その後、名称変更
$ cd /home/end0tknr/proj/django $ django-admin startproject config $ mv config myproj $ cd myproj $ tree ├ config │ ├ asgi.py │ ├ settings.py │ ├ urls.py │ └ wsgi.py └ manage.py
付属サーバによる接続確認
vi config/settings.py
ALLOWED_HOSTS = ['*'] # old) ALLOWED_HOSTS = [] TIME_ZONE = 'Asia/Tokyo' # old) TIME_ZONE = 'UTC'
付属サーバ起動と、接続確認
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行後、ブラウザでアクセスすると、以下が表示
簡易アプリ作成 - その1. VIEW
manage.py startapp $app_name
$ cd /home/end0tknr/proj/django/myproj $ python3 manage.py startapp books $ tree ├ books ## NEW │ ├ admin.py ## 〃 │ ├ apps.py ## 〃 │ ├ migrations/ ## 〃 │ ├ models.py ## 〃 │ ├ tests.py ## 〃 │ └ views.py ## 〃 ├ config │ ├ asgi.py │ ├ settings.py │ ├ urls.py │ └ wsgi.py ├ db.sqlite3 └ manage.py
config/settings.py 修正
INSTALLED_APPS = [ 'books', ## ADD 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
アプリ用ルーティング設定
config/urls.py 修正
from django.contrib import admin from django.urls import path, include ## ADD urlpatterns = [ path('admin/', admin.site.urls), path('books/', include('books.urls')), ## ADD ]
books/urls.py 追加
from django.urls import path from . import views # 名前空間:reverseメソッドやurlタグから # 「<名前空間名>:<名前空間内のname>」でurlで逆引きできる app_name = 'books' urlpatterns = [ path('', views.list_books, name='list_books' ), ]
books/views.py 変更
from django.shortcuts import render from django.http import HttpResponse def list_books(request): return HttpResponse("Hello world!")
付属サーバ起動と、動作確認
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行後、http://localhost:8080/books/ へ、 ブラウザでアクセスすると、「Hello world!」と表示されれば、OK
簡易アプリ作成 - その2. MODEL
MODELクラス作成 - books/models.py の変更
from django.db import models class Book(models.Model): book_id = models.CharField(max_length=32) title = models.CharField(max_length=256) author = models.CharField(max_length=256) def __str__(self): return self.title
DBマイグレーション ファイル作成
$ python3 manage.py makemigrations Migrations for 'books': books/migrations/0001_initial.py - Create model Book
$ less books/migrations/0001_initial.py
from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [] operations = [ migrations.CreateModel( name='Book', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('book_id',models.CharField(max_length=32)), ('title', models.CharField(max_length=256)), ('author', models.CharField(max_length=256)), ], ), ]
DBマイグレート実行
$ python3 manage.py migrate Operations to perform: Apply all migrations: admin, auth, books, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK 【略】 Applying books.0001_initial... OK Applying sessions.0001_initial... OK
DBスキーマ確認
$ python3 manage.py dbshell SQLite version 3.34.1 2021-01-20 14:10:07 sqlite> .tables auth_group books_book auth_group_permissions django_admin_log auth_permission django_content_type auth_user django_migrations auth_user_groups django_session auth_user_user_permissions sqlite> .schema books_book CREATE TABLE IF NOT EXISTS "books_book" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "book_id" varchar(32) NOT NULL, "title" varchar(256) NOT NULL, "author" varchar(256) NOT NULL );
付属する管理ツール
管理USER作成
$ python3 manage.py createsuperuser Username (leave blank to use 'end0tknr'): Email address: 【空でもOK】 Password: Password (again): Superuser created successfully.
管理対象MODEL追加 - books/admin.py の修正
from django.contrib import admin from .models import Book admin.site.register(Book)
管理ツールによるDB編集
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行し、http://localhost:8080/admin/ へ、アクセスすると、 次のような画面が表示され、ログイン後、dbを編集できます
HTMLテンプレート
テンプレート用DIRの追加 - config/settings.py の修正
import os ## ADD TEMPLATES = [ {'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], ## CHANGE }]
テンプレート用DIRの追加 - mkdir templates
$ cd /home/end0tknr/proj/django/myproj mkdir -p templates mkdir -p templates/books $ tree ├ books │ ├ admin.py │ ├ apps.py │ ├ migrations │ │ └ 0001_initial.py │ ├ models.py │ ├ tests.py │ ├ urls.py │ └ views.py ├ config │ ├ asgi.py │ ├ settings.py │ ├ urls.py │ └ wsgi.py ├ db.sqlite3 ├ manage.py └ templates ## NEW └ books ## 〃
テンプレート ファイル作成
$ vi templates/layout.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block content %}{% endblock %} </body> </html>
$ vi templates/books/list_books.html
{% extends 'layout.html' %} {% block content %} <table> <thead> <tr> <th>Book ID</th> <th>Title</th> <th>Author</th> <th>Action</th> </tr> </thead> <tbody> {% if books %} {% for book in books %} <tr> <td><a href="/books/{{ book.book_id }}">{{ book.book_id }}</a></td> <td>{{ book.title }}</td> <td>{{ book.author }}</td> <td><a href="/books/{{ book.book_id }}/edit">[Edit]</a></td> </tr> {% endfor %} {% else %} <tr> <td colspan=4>No books.</td> </tr> {% endif %} </tbody> </table> {% endblock %}
VIEWメソッドの追加 - books/views.py の変更
from django.shortcuts import render from django.http import HttpResponse from django.template import loader from .models import Book # def list_books(request): # return HttpResponse("Hello world!") def list_books(request): books = Book.objects.all() context = { 'title': 'List Books', 'books': books, } template = loader.get_template('books/list_books.html') return HttpResponse(template.render(context, request))
付属サーバによる動作確認
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行後、http://localhost:8080/books/ へ、 ブラウザでアクセスすると、先程、管理ツールで登録したものが表示されます
DB変更 - CRUD
編集用URL追加 - books/urls.py
from django.urls import path from . import views # 名前空間:reverseメソッドやurlタグから # 「<名前空間名>:<名前空間内のname>」でurlで逆引きできる app_name = 'books' urlpatterns = [ path('', views.list_books, name='list_books' ), path('<str:book_id>', views.detail_book,name='detail_book'), path('<str:book_id>/edit',views.edit_book, name='edit_book' ), ## ADD ]
編集用テンプレート作成 - templates/books/edit_book.html
※ 以下にある「{% url 'books:edit_book' book.book_id %}」は、 「/books/1/edit」のように実体化されます。
{% extends 'layout.html' %} {% block content %} <form method="POST" action="{% url 'books:edit_book' book.book_id %}"> {% csrf_token %} <input type="hidden" name="mode" value="{{ mode }}"> <table> <tr> <th>Book ID</th> <td><input type="text" name="book_id" readonly value="{{ book.book_id }}"></td> </tr> <tr> <th>Title</th> <td><input type="text" name="title" {% if mode != 'input' %}readonly{% endif %} value="{{ book.title }}"></td> </tr> <tr> <th>Author</th> <td><input type="text" name="author" {% if mode != 'input' %}readonly{% endif %} value="{{ book.author }}"></td> </tr> </table> <div class="basic-block"> {% if mode == 'input' %} <button type="button" onclick="location.href='{% url 'books:list_books' %}'">Return</button> <button type="submit">OK</button> {% elif mode == 'confirm' %} <button type="button" onclick="history.back()">Back</button> <button type="submit">OK</button> {% elif mode == 'result' %} <button type="button" onclick="location.href='{% url 'books:list_books' %}'">Return</button> {% endif %} </div> </form> {% endblock %}
CRUD処理追加 - books/views.py
def edit_book(request, book_id): if request.method == 'GET': return edit_book_input(request, book_id) if request.method == 'POST': if request.POST['mode'] == 'input': return edit_book_confirm(request, book_id) if request.POST['mode'] == 'confirm': return edit_book_result(request, book_id) def edit_book_input(request, book_id): try: book = Book.objects.get(book_id=book_id) except Book.DoesNotExist: book = None context = { 'title': 'Edit Book(input)', 'mode': 'input', 'book': book, } template = loader.get_template('books/edit_book.html') return HttpResponse(template.render(context, request)) def edit_book_confirm(request, book_id): book = Book() book.book_id = request.POST['book_id'] book.title = request.POST['title'] book.author = request.POST['author'] context = { 'title': 'Edit Book(confirm)', 'mode': 'confirm', 'warning_message': 'Are you sure you want to save?', 'book': book, } template = loader.get_template('books/edit_book.html') return HttpResponse(template.render(context, request)) def edit_book_result(request, book_id): try: book = Book.objects.get(book_id=book_id) book.book_id = request.POST['book_id'] book.title = request.POST['title'] book.author = request.POST['author'] book.save() ## 保存 except Book.DoesNotExist: book = None context = { 'title': 'Edit Book(result)', 'mode': 'result', 'success_message': 'Success!', 'book': book, } template = loader.get_template('books/edit_book.html') return HttpResponse(template.render(context, request))
付属サーバによる動作確認
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行後、http://localhost:8080/books/ へ、 アクセスすると、以下の画面で、DB変更を確認できます
静的ファイル
静的ファイル用DIR追加 - config/settings.py の変更
STATIC_URL = 'static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )
静的ファイル用DIR追加 - mkdir static
$ cd /home/end0tknr/proj/django/myproj $ mkdir -p static/js $ mkdir -p static/css $ mkdir -p static/images $ tree ├ books │ ├ admin.py │ ├ apps.py │ ├ migrations │ │ └ 0001_initial.py │ ├ models.py │ ├ tests.py │ ├ urls.py │ └ views.py ├ config │ ├ asgi.py │ ├ settings.py │ ├ urls.py │ └ wsgi.py ├ db.sqlite3 ├ manage.py ├ static ## NEW │ ├ css ## 〃 │ ├ images ## 〃 │ └ js ## 〃 └ templates ├ books │ └ list_books.html └ layout.html
静的ファイルの作成
table { border-collapse: collapse; margin-bottom: .5rem; } table th, table td { border: 1px solid #999; padding: .1rem .3rem; } table th { background-color: #ddd; } button { line-height: 1.2rem; min-width: 6rem; }
$ vi templates/layout.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{{ title }}</title> <link rel="stylesheet" href="/static/css/style.css"> <!--ADD--> </head> <body> <h1>{{ title }}</h1> {% block content %}{% endblock %} </body> </html>
付属サーバによる動作確認
$ python3 manage.py runserver 0.0.0.0:8080
上記を実行後、http://localhost:8080/books/ へ、 アクセスすると、以下が表示