Djangoプロトタイプのすゝめ
自分がまだ扱ったことのないフレームワークや言語を習得する際、以下のような手順を踏むべきだと考えています。
- テキストの解説を見ながらコードを模写する
- (チョー)簡単なアプリを作ってみる
- (ちゃんとした)アプリを作ってみる
- 繰り返し使う
- 気づいたら習得している
この記事では2.を中心的に取り上げます。
さて、何から始めたらよいのか
テキストを模写しているときはテキストの通りに進めたら、いつの間にか1つの機能が完成している(?!)という状況でした。
ここで、何から始めればいいの?ってなると思います。
まずは最初のステップについて説明します。
まずは何を作るか
ここでは、(チョー)簡単なアプリを作ります。
(習得していない状態でいきなり本格的なアプリを作ろうとすると詰みます)
(チョー)簡単なアプリとは...?
どのアプリでも(ほぼ)必ずあるものとは?
それは...
CRUD操作ができることこれを持つアプリとして以下のようなものがあります。
- ブログ
- タスク管理アプリ
- ミニSNS
ということで、今回はブログを作ってみます
環境構築をする
今回はDockerを使って環境構築をしていきます。
プロジェクトフォルダを作成して、そのフォルダに移動しましょう。
プロジェクトフォルダ直下に以下のファイルを追加します。
FROM python:3.11
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ADD . /code/
Django == 4.2.2
psycopg2-binary
django-environ
version: "3"
services:
db:
image: postgres
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
django:
build:
context: .
dockerfile: Dockerfile
command: python3 manage.py runserver 0.0.0.0:8000
container_name: django
env_file:
- .env
volumes:
- ./django_app:/code
ports:
- "8000:8000"
depends_on:
- db
volumes:
postgres_data:
POSTGRES_DB: "[データベース名]"
POSTGRES_USER: "[データベースのユーザ名(管理者)]"
POSTGRES_PASSWORD: "[データベースのパスワード]"
今後のアプリ開発ではGit管理をするので、それも意識して.env
ファイルを作成します。
プロジェクトフォルダに移動して以下のコマンドを実行しましょう.
コマンドを実行するときは、そのコマンドの意味を理解してから実行するようにしましょう。
以下のコマンドはプロジェクト名もそのまま記述しています。
docker-compose build
docker-compose django django-admin startproject django_app
アプリのひな形を作る
以下のコマンドを実行してアプリのひな形を作成しましょう
docker-compose run django python manage.py startapp blog
アプリを作ってみる
環境構築は上の解説を参考にしてください。
((私のように)環境構築であまり詰まってほしくはない...)
Django以外のアプリ開発経験がある方は挑戦してみると色々学ぶことができます
さて、今回作成するアプリの概要を説明します。
コード自体は最後に載せるので、まずは挑戦してみてください
要件
作るもの
- ブログ
(といっても、記事の編集と削除は省きます)
手順
- DBのことは考えず、views.pyからtemplateファイルに値を渡してみましょう
- models.pyで、テーブルを定義しましょう(マイグレーションもお忘れなく)
- DBから値を取得してtemplateファイルに値を渡しましょう
最終的なファイルたち
<!DOCTYPE html>
<html>
<head>
<title>{{ page_title }}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
</head>
<body>
<div class="container">
<h1 class="my-4">{{ page_title }}</h1>
<a href="{% url "create" %}" class="btn btn-success mb-4">投稿する</a>
{% for post in posts %}
<div class="list-group">
<a
href="{% url 'detail' post.id %}"
class="list-group-item list-group-item-action"
>
<h5 class="mb-1">{{ post.title }}</h5>
<small class="text-muted">{{ post.username }}</small>
<p class="mb-1">{{ post.text }}</p>
</a>
</div>
{% endfor %}
</div>
</body>
</html>
<!-- blog/templates/blog/create.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ page_title }}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
</head>
<body>
<div class="container">
<h1 class="my-4">Create a New Blog Post</h1>
<form method="post" action="{% url "create" %}">
{% csrf_token %}
<div class="form-group">
<label for="title">Title:</label>
<input
type="text"
class="form-control"
id="title"
name="title"
required
/>
</div>
<div class="form-group">
<label for="username">Username:</label>
<input
type="text"
class="form-control"
id="username"
name="username"
required
/>
</div>
<div class="form-group">
<label for="text">Content:</label>
<textarea
class="form-control"
id="content"
name="text"
rows="5"
required
></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</body>
</html>
<!-- blog/templates/blog/show.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ page_title }}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
</head>
<body>
<div class="container">
<h1 class="my-4">{{ post.title }}</h1>
<p class="text-muted">{{ post.username }}</p>
<p>{{ post.text }}</p>
<a href="{% url 'index' %}" class="btn btn-primary">全件表示に戻る</a>
</div>
</body>
</html>
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .forms import PostForm
from .models import Post
def index(request):
posts = Post.objects.all()
params = {
'page_title': '記事一覧',
'posts': posts,
}
return render(request, 'blog/index.html', params)
def detail(request, post_id):
post = Post.objects.get(id=post_id)
params = {
'page_title': '記事詳細',
'post': post,
}
return render(request, 'blog/detail.html', params)
def create(request):
if (request.method == 'POST'):
obj = Post()
post = PostForm(request.POST, instance=obj)
post.save()
return redirect(to='/blog')
params = {
'page_title': '投稿する',
'form': PostForm(),
}
return render(request, 'blog/create.html', params)
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['username', 'title', 'text']
labels = {
'title': '記事タイトル',
'text': '記事本文',
}
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'text': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
}
from django.db import models
class Post(models.Model):
username = models.CharField(max_length=255, default='default_name')
title = models.CharField(max_length=100)
text = models.TextField(max_length=300, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<int:post_id>', views.detail, name='detail'),
path('create', views.create, name='create'),
path('edit', views.edit, name='edit'),
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
]
# 変更箇所のみ記載
import environ
env = environ.Env()
environ.Env.read_env()
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
POSTGRES_DB = env('POSTGRES_DB')
POSTGRES_USER = env('POSTGRES_USER')
POSTGRES_PASSWORD = env('POSTGRES_PASSWORD')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': POSTGRES_DB,
'PASSWORD': POSTGRES_PASSWORD,
'USER': POSTGRES_USER,
'HOST': 'db',
}
}
おわりに
無事、ブログアプリ完成したでしょうか?
環境や私の不備の関係でコードが思うように動かなかったということがあるかもしれません...。
コードが動かないときのtipsを記しておきます
-
コンソールに表示されているエラー文を読む
(このコマンドを実行しろ!とかの文章が表示される場合があります) -
エラー文を検索してみる
Qiitaとかいろんなサイトで、同じところで詰まっている方がいるかもしれません。 -
ChatGPTに相談してみる
ある程度は相談に乗ってくれます。ChatGPTの文章に含まれるキーワードを使って検索してみるといいかもしれません。