プロジェクトのセットアップ
プロジェクトとアプリの作成
pip install django django-admin startproject mysite cd mysite python manage.py startapp blog
よく使うコマンド
runserverポート 8000 で開発サーバーを起動
makemigrationsモデル変更からマイグレーションファイルを生成
migrateデータベースにマイグレーションを適用
createsuperuser管理者スーパーユーザーを作成
shellDjango 付きの対話型 Python シェル
testテストスイートを実行
プロジェクト構造
manage.pyCLI エントリーポイント
settings.pyプロジェクト設定
urls.pyルート URL 設定
wsgi.py / asgi.pyサーバーエントリーポイント
apps/models.pyデータベースモデル
apps/views.pyリクエストハンドラ
モデル
モデルの定義
from django.db import models class Post(models.Model): title = models.CharField(max_length=200) body = models.TextField() created = models.DateTimeField(auto_now_add=True) published = models.BooleanField(default=False)
フィールドの種類
CharField(max_length=N)短いテキスト(max_length 必須)
TextField()長いテキスト(制限なし)
IntegerField()整数値
FloatField()浮動小数点数
BooleanField()True / False
DateTimeField()日付と時刻
EmailField()バリデーション付きメールアドレス
FileField(upload_to='')ファイルアップロード
リレーションシップ
author = models.ForeignKey( User, on_delete=models.CASCADE ) tags = models.ManyToManyField(Tag, blank=True) profile = models.OneToOneField(User, on_delete=models.CASCADE)
Meta とメソッド
class Meta: ordering = ['-created'] verbose_name_plural = 'posts' def __str__(self): return self.title
ビュー
関数ベースビュー
from django.shortcuts import render, get_object_or_404 def post_list(request): posts = Post.objects.filter(published=True) return render(request, 'blog/list.html', {'posts': posts})
クラスベースビュー
from django.views.generic import ListView, DetailView class PostListView(ListView): model = Post template_name = 'blog/list.html' context_object_name = 'posts' paginate_by = 10
よく使う CBV
ListViewオブジェクトのリストを表示
DetailView単一オブジェクトを表示
CreateViewオブジェクト作成フォーム
UpdateViewオブジェクト編集フォーム
DeleteView確認してオブジェクトを削除
TemplateViewテンプレートをレンダリング(モデルなし)
JSON レスポンス
from django.http import JsonResponse def api_posts(request): data = list(Post.objects.values('id', 'title')) return JsonResponse(data, safe=False)
テンプレート
テンプレート構文
{{ variable }} {{ post.title|truncatewords:30 }} {% if user.is_authenticated %}

Welcome, {{ user.username }}!

{% endif %}
ループと条件分岐
{% for post in posts %}

{{ post.title }}

{% if forloop.last %}
{% endif %} {% empty %}

No posts yet.

{% endfor %}
テンプレート継承
{# base.html #} {% block content %}{% endblock %} {# child.html #} {% extends "base.html" %} {% block content %}

Hello

{% endblock %}
よく使うフィルター
|date:"Y-m-d"日付のフォーマット
|default:"N/A"空の値のフォールバック
|lengthリストの件数をカウント
|truncatewords:NN 単語に制限
|safe安全な HTML としてマーク(エスケープなし)
|slugifyURL 安全な小文字文字列
URL
URL パターン
from django.urls import path, include urlpatterns = [ path('', views.index, name='index'), path('post//', views.detail, name='detail'), path('blog/', include('blog.urls')), ]
パスコンバーター
<int:pk>整数(例: 42)
<str:slug>スラッシュを含まない文字列
<slug:slug>スラッグ(文字、数字、ハイフン)
<uuid:id>UUID 形式
<path:rest>スラッシュを含む完全なパス
URL の逆引き
from django.urls import reverse url = reverse('detail', kwargs={'pk': 1}) # テンプレートで: {% url 'detail' pk=post.pk %}
フォーム
モデルフォーム
from django import forms class PostForm(forms.ModelForm): class Meta: model = Post fields = ['title', 'body', 'published']
ビューでフォームを処理
def create_post(request): form = PostForm(request.POST or None) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.save() return redirect('detail', pk=post.pk) return render(request, 'blog/form.html', {'form': form})
テンプレートでのフォーム
{% csrf_token %} {{ form.as_p }}
バリデーション
def clean_title(self): title = self.cleaned_data['title'] if len(title) < 5: raise forms.ValidationError("Title too short.") return title
管理画面
モデルの登録
from django.contrib import admin from .models import Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ['title', 'author', 'created', 'published'] list_filter = ['published', 'created'] search_fields = ['title', 'body']
管理画面オプション
list_display一覧ビューのカラム
list_filterサイドバーのフィルターオプション
search_fields検索可能なフィールド
prepopulated_fields自動入力(例: タイトルからスラッグ)
readonly_fields管理画面で編集不可
orderingデフォルトのソート順
ORM クエリ
基本クエリ
Post.objects.all() # すべてのレコード Post.objects.get(pk=1) # 1件(存在しない場合は例外) Post.objects.filter(published=True) # クエリセット Post.objects.exclude(draft=True) # 一致を除外 Post.objects.count() # 合計件数
フィールドルックアップ
field__exact完全一致(デフォルト)
field__icontains大文字小文字を区別しない部分一致
field__gt / __ltより大きい / より小さい
field__gte / __lte以上 / 以下
field__in=[1,2,3]リスト内の値
field__isnull=TrueNULL である
field__startswith文字列で始まる
field__range=(a,b)a 以上 b 以下
チェーンと集計
from django.db.models import Q, Count, Avg Post.objects.filter( Q(title__icontains='django') | Q(body__icontains='django') ).order_by('-created')[:10] Post.objects.aggregate(avg_views=Avg('views'))
作成、更新、削除
post = Post.objects.create(title='New', body='...') post.title = 'Updated' post.save() Post.objects.filter(draft=True).update(published=False) post.delete()
認証
ログイン / ログアウト
from django.contrib.auth import authenticate, login, logout user = authenticate(request, username='admin', password='pw') if user is not None: login(request, user)
ビューの保護
from django.contrib.auth.decorators import login_required @login_required def dashboard(request): return render(request, 'dashboard.html')
認証 URL
# urls.py path('accounts/', include('django.contrib.auth.urls')) # 提供: login、logout、password_change、password_reset
テンプレートでの認証
{% if user.is_authenticated %}

Hi, {{ user.username }}

Logout {% else %} Login {% endif %}
設定
主要な設定
DEBUG開発時は True、本番は False
ALLOWED_HOSTS有効なホスト名のリスト
SECRET_KEY暗号署名キー(秘密に保つ)
DATABASESDB エンジン、名前、ホスト、認証情報
INSTALLED_APPS登録済みアプリのリスト
STATIC_URL静的ファイルの URL プレフィックス
MEDIA_URL / MEDIA_ROOTユーザーアップロードファイルのパス
データベース設定
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydb', 'USER': 'dbuser', 'HOST': 'localhost', 'PORT': '5432', } }
静的ファイル
STATIC_URL = '/static/' STATICFILES_DIRS = [BASE_DIR / 'static'] # テンプレートで: {% load static %} #