目次
Django
0.コマンド一覧
1.環境構築
2.最初のプロジェクト
2.1 Hello, World
2.2 home.html
3.モデル設計
3.1 ブログセクション設計
3.2 実装コード
3.3 モデルAPIのテスト
3.3.1 Pythonコマンドでのオブジェクト作成
3.3.2 モデルマネージャーによるオブジェクト作成
4.ビュー関数
5.検索エンジン設定
6.テンプレート
7.フォーム
7.1 はじめに
7.2 Forms API
7.3 Bootstrapフォームレンダリング
pyファイル詳細
1.settings.py
1.1 静的ファイル
1.2 INSTALLED_APPS
1.3 X_FRAME_OPTIONS
2.urls.py
3.models.py
4.urls.py
よく使う関数
Django
Django開発メモ
0.コマンド一覧
-
Djangoインストール
pip install django==#version# -
プロジェクト作成
cd Django django-admin startproject #プロジェクト名# -
アプリケーション作成
アプリは機能モジュールです
python manage.py startapp #アプリ名# -
プロジェクト実行
python manage.py runserver -
プロジェクト停止
ctrl + c -
仮想環境終了
deactivate -
モデルマイグレーション
boards/migrations ディレクトリに0001_initial.pyというファイルが作成されます。これはアプリケーションモデルの現在の状態を表します。次のステップで、Djangoはこのファイルを使用してテーブルとカラムを作成します。
python manage.py makemigrations生成されたファイルをデータベースに適用します
python manage.py migrate -
Pythonシェル
python普通のPythonインタープリタセッションを起動します。任意のPythonコードを実行できますが、Djangoプロジェクトの設定や構成は自動的にロードされません。
python manage.py shell特別なDjangoインタラクティブシェルを起動します。現在のDjangoプロジェクトの設定と構成をロードし、シェル内でDjangoプロジェクトと直接やりとりできます。このシェルでは、Djangoのモデルやマネージャーなど、Django固有の機能を手動で設定することなく直接インポートして使用できます。
-
インタラクティブコンソール終了
exit() -
スーパーユーザー作成
python manage.py createsuperuser
1. 環境構築
2.最初のプロジェクト
2.1 Hello, World
boardsアプリを作成
boards/views.py
from django.http import HttpResponse
def home(request):
return HttpResponse('Hello, World!')
view homeを定義しました。homeはrequestを受け取り、文字列'Hello, World!'を返します。
djangoはurls.pyでview homeを呼び出します。
boards/urls.py
from django.conf.urls import url
from django.contrib import admin
from boards import views
urlpatterns = [
re_path(r'^$', views.home, name='home'),
re_path(r'^admin/', admin.site.urls),
]
re_path(r'^$', views.home, name='home') の役割は:
-
正規表現を使ってサイトのURLパスを一致させる文字列を定義します。
正規表現を使用:re_path、正規表現を使用しない:path、古いバージョンのDjangoでは:url
-
Webページがそのパスにアクセスした場合、リクエストは
views.homeビュー関数で処理されます。 -
このURLパターンに
homeという名前を指定し、他の場所から参照できるようにします。この名前はプロジェクト内の他の場所で使用できます。例えば、テンプレートで
{% url 'home' %}を使ってこのURLを生成したり、ビュー関数でreverse('home')を使ってこのURLを逆引きしたりできます。名前付きURLの利点は、URLパターンが変更されても名前が変わらなければ、他のコードを変更する必要がないことです。
2.2 home.html
home.html
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Boards</h1>
<ul>
{% for board in boards %}
<li>{{ board.name }} - {{ board.description }}</li>
{% endfor %}
</ul>
</body>
</html>
boards/view.py
def Home(request):
boards = Board.objects.all()
return render(request, 'home.html', {'boards': boards})
renderはDjangoのビュー関数で、レンダリングされたHTMLページを返すための一般的なメソッドです。データ{'boards': boards}をページ'home.html'のテンプレートに渡し、HTTPレスポンスを生成してクライアントに返します。
request: HTTPリクエストオブジェクトで、クライアントが送信したリクエスト情報を含みます。'home.html': ページ名で、Djangoはこの名前を使って設定されたテンプレートディレクトリからテンプレートファイルを検索してレンダリングします。{'boards': boards}: テンプレートに渡すデータを含む辞書です。この例では、boardsはBoardオブジェクトのクエリセット(QuerySet)であり、テンプレート内で変数名boardsを通してアクセスされます。
3. モデル設計
3.1 ブログセクション設計
Web Boardクラス図
- Board:セクション
- Topic:トピック
- Post:投稿(注:トピックの返信またはコメント)
トピック(Topic)では、どのセクションに属するかを特定するフィールド(注:外部キーで関連付け)が必要です。
同様に、投稿(Post)にもどのトピックに属するかを示すフィールドが必要で、特定のトピック内で作成された投稿をリストアップできます。
最後に、誰がトピックを開始したか、誰が投稿したかを示すフィールドが必要です。
詳細設計
Board モデルには2つのフィールドがあります。
- nameフィールドは一意である必要があります。重複名を防ぐためです。
- descriptionはこのセクションの目的を説明するために使用されます。
Topic モデルには4つのフィールドがあります:
- subjectはトピックの内容を表します。
- last_updateはトピックの並び替えに使用されます。
- starterは誰がトピックを開始したかを識別します。
- boardはそれがどのセクションに属するかを指定します。
Post モデルには1つあります。
- messageフィールドは返信の内容を格納します。
- created_atは並び替え時に使用されます(最初に投稿された投稿が最初になります)。
- updated_atはユーザーに内容が更新されたことを示します。
- 同時に、対応するUserモデルへの参照も必要です。
- 投稿は誰が作成したか、誰が更新したかを示します。
最後にUserモデルです。クラス図ではusername、password、email、is_superuserフラグのみを示しています。これらは現在使用しているほとんどすべてのものです。
注意すべきは、Userモデルを作成する必要はないということです。なぜなら、Djangoはcontribパッケージに既にUserモデルを内蔵しているからです。直接それを使用します。
3.2 実装コード
boards/models.py
from django.db import models
from django.contrib.auth.models import User
class Board(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100)
class Topic(models.Model):
subject = models.CharField(max_length=255)
last_updated = models.DateTimeField(auto_now_add=True)
board = models.ForeignKey(Board, related_name='topics')
starter = models.ForeignKey(User, related_name='topics')
class Post(models.Model):
message = models.TextField(max_length=4000)
topic = models.ForeignKey(Topic, related_name='posts')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(null=True)
created_by = models.ForeignKey(User, related_name='posts')
updated_by = models.ForeignKey(User, null=True, related_name='+')
Boardモデル
name: 文字数が30文字以内の文字列フィールドで、一意である必要があります。description: 文字数が100文字以内の文字列フィールドです。
Topicモデル
subject: 文字数が255文字以内の文字列フィールドです。last_updated: 日時フィールドで、Topicオブジェクトが作成されたときに現在の時間を自動的に設定します。board: Boardモデルに関連する外部キーフィールドで、related_name='topics'を使用します。Boardが削除された場合、関連するTopicも削除されます。starter: Userモデルに関連する外部キーフィールドで、related_name='topics'を使用します。Userが削除された場合、関連するTopicも削除されます。views: 正の整数フィールドで、初期値は0で、Topicの閲覧回数を記録します。
Postモデル
message: 文字数が4000文字以内のテキストフィールドです。topic: Topicモデルに関連する外部キーフィールドで、related_name='posts'を使用します。Topicが削除された場合、関連するPostも削除されます。created_at: 日時フィールドで、Postオブジェクトが作成されたときに現在の時間を自動的に設定します。updated_at: 日時フィールドで、空にできます。Postの更新時間を記録します。created_by: Userモデルに関連する外部キーフィールドで、related_name='posts'を使用します。Userが削除された場合、関連するPostも削除されます。updated_by: Userモデルに関連する外部キーフィールドで、空にできます。related_name='+'を使用します。Userが削除された場合、関連するPostも削除されます。
Boardモデルはフォーラムのセクションを表し、名前と説明を含み、関連する投稿数や最新の投稿を取得するメソッドを提供します。
Topicモデルはフォーラムのトピックを表し、トピック名、最終更新日時、所属セクション、開始ユーザー、閲覧回数を含みます。
Postモデルはフォーラムの投稿を表し、メッセージ内容、所属トピック、作成時間、更新時間、作成ユーザー、更新ユーザーを含みます。
対応するMySQLテーブル作成SQL
CREATE TABLE `board` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(30) UNIQUE NOT NULL,
`description` VARCHAR(100) NOT NULL
);
CREATE TABLE `topic` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`subject` VARCHAR(255) NOT NULL,
`last_updated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`board_id` INT NOT NULL,
`starter_id` INT NOT NULL,
`views` INT UNSIGNED NOT NULL DEFAULT 0,
FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`starter_id`) REFERENCES `auth_user`(`id`) ON DELETE CASCADE
);
CREATE TABLE `post` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`message` TEXT NOT NULL,
`topic_id` INT NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME,
`created_by_id` INT NOT NULL,
`updated_by_id` INT,
FOREIGN KEY (`topic_id`) REFERENCES `topic`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`created_by_id`) REFERENCES `auth_user`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`updated_by_id`) REFERENCES `auth_user`(`id`) ON DELETE CASCADE
);
related_nameは逆方向のクエリを行うための属性です。モデルに外部キー(ForeignKey)または多対多関係(ManyToManyField)を定義すると、Djangoは自動的に逆方向の関係を作成し、関連するモデルからこのモデルにアクセスできるようにします。related_nameを使用すると、この逆方向の関係にカスタム名を指定できます。
- Topicインスタンスを取得
topic = Topic.objects.get(id=1)
- デフォルトの逆方向関係名を使用(post_set)
posts_default = topic.post_set.all()
- カスタムの逆方向関係名を使用
posts_custom = topic.posts.all() #該当のTopicに関連するすべてのPostオブジェクトを取得
HTMLテンプレートファイルでは、括弧を使わず、
board.topics.allを使用します
データをフィルタリングすることも可能です
board.topics.filter(subject__contains='Hello')
3.3 モデルAPIのテスト
3.3.1 Pythonコマンドでのオブジェクト作成
Pythonシェルを起動
Boardクラスをインポート
from boards.models import Board
新しいboardオブジェクトを作成
board = Board(name='Django', description='This is a board about Django.')
オブジェクトをデータベースに保存
board.save()
3.3.2 モデルマネージャーによるオブジェクト作成
Djangoの標準属性objectsを通じてモデルマネージャーにアクセス
board = Board.objects.create(name='Python', description='General discussion about Python.')
また、objectsを使ってデータベース内のすべての既存セクションをリストアップすることもできます
Board.objects.all()
データベースをクエリして単一のオブジェクトを返すことも可能です
board = Board.objects.get(id=1)
board.name
'Django'
存在しないオブジェクトをクエリすると例外が発生します。
getメソッドのパラメータはモデルの任意のフィールドにすることができます。一意ではない識別子をクエリすると複数のオブジェクトが返され、例外が発生します。
4.ビュー関数
5.検索エンジン設定
manage.pyがあるディレクトリに templates という新しいフォルダを作成します:
myproject/
|-- myproject/
| |-- boards/
| |-- myproject/
| |-- templates/ <-- ここ
| +-- manage.py
+-- venv/
templatesフォルダ内にhome.htmlというHTMLファイルを作成します:
templates/home.html
続きあり
6. テンプレート
7. フォーム
7.1 はじめに
csrf_token テンプレートタグ:
{% csrf_token %}
Djangoは CSRF Token(Cross-Site Request Forgery Token)を使用してすべてのPOSTリクエストを保護します。
データ取得
<input type="text" id="id_subject" name="subject">
<input type="text" id="id_message" name="message">
subject = request.POST['subject']
message = request.POST['message']
具体的な実装
from django.contrib.auth.models import User
from django.shortcuts import render, redirect, get_object_or_404
from .models import Board, Topic, Post
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
if request.method == 'POST':
subject = request.POST['subject']
message = request.POST['message']
user = User.objects.first() # TODO: 一時的にログインユーザーとして使用
topic = Topic.objects.create(
subject=subject,
board=board,
starter=user
)
post = Post.objects.create(
message=message,
topic=topic,
created_by=user
)
return redirect('board_topics', pk=board.pk)
return render(request, 'new_topic.html', {'board': board}
)
7.2 Forms API
Forms APIはdjango.formsモジュールで利用できます。
Djangoには2種類のフォームがあります:forms.Form と forms.ModelForm です。
Formクラスは汎用的なフォーム実装です。アプリケーションモデルと直接関連していないデータを処理するために使用できます。
ModelFormはFormのサブクラスで、モデルクラスに関連付けられます。
boards/forms.py
from django import forms
from .models import Topic
class NewTopicForm(forms.ModelForm):
message = forms.CharField(widget=forms.Textarea(), max_length=4000)
# Django Forms APIは強力なフォーム検証機能を提供します。フォームフィールドは必須フィールド、最大長、正規表現などの各種検証ルールを定義できます。
# form.is_valid()メソッドは自動的にフォームデータがこれらのルールに適合するか確認します。
class Meta:
model = Topic # フォームに関連付けるモデルはTopicです
fields = ['subject', 'message'] # フォームに含まれるフィールドはsubjectとmessageです
boards/views.py # フォーム未使用
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
if request.method == 'POST':
subject = request.POST['subject']
message = request.POST['message']
user = User.objects.first()
topic = Topic.objects.create(
subject=subject,
board=board,
starter=user
)
post = Post.objects.create(
message=message,
topic=topic,
created_by=user
)
return redirect('board_topics', pk=board.pk)
return render(request, 'new_topic.html', {'board': board})
boards/views.py # フォーム使用
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk) # Boardオブジェクトを取得します。存在しない場合は404エラーを返します。
user = User.objects.first() # TODO: 現在ログイン中のユーザーを取得
if request.method == 'POST': # POSTリクエストの場合、ユーザーがフォームデータを送信したことを意味します。
form = NewTopicForm(request.POST) # 新しいNewTopicFormフォームインスタンスを作成し、リクエストのPOSTデータを渡します。
if form.is_valid(): # form.is_valid()でフォームデータが有効かどうかを確認します。
topic = form.save(commit=False) # form.saveでTopicオブジェクトを作成しますが、データベースには保存しません。
topic.board = board
topic.starter = user
topic.save()
post = Post.objects.create(
message=form.cleaned_data.get('message'),
topic=topic,
created_by=user
)
return redirect('board_topics', pk=board.pk) # TODO: 作成されたトピックページにリダイレクト
else:
form = NewTopicForm() # POSTリクエスト以外の場合は、空のNewTopicFormフォームインスタンスを作成します。
return render(request, 'new_topic.html', {'board': board,'form': form})
中心部分
if request.method == 'POST':
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save()
return redirect('board_topics', pk=board.pk)
else:
form = NewTopicForm()
return render(request, 'new_topic.html', {'form': form})
new_topic.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Post</button>
</form>
formには3つのレンダリングオプションがあります:form.as_table、form.as_ul、form.as_p。
これはフォームのすべてのフィールドを素早くレンダリングする方法です。名前通り、as_tableはtableタグを使用して入力をフォーマットし、as_ulはliタグを使用します。
7.3 Bootstrapフォームレンダリング
保留中
pyファイル詳細
1.settings.py
1.1 静的ファイル
STATICFILES_DIRSは静的ファイルの検索ディレクトリを指定するために使用されます。
プロジェクトのルートディレクトリにstaticフォルダを作成します。
settings.py
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
Python3.4以降のバージョンではBASE_DIR / 'static'を使用することをお勧めします。
以前のバージョンではos.path.join(BASE_DIR, 'static')を使用します。
機能は同等です。
テンプレートの先頭で{ % load static % }タグを使用します。
1.2 INSTALLED_APPS
1.3 X_FRAME_OPTIONS
レスポンスヘッダーのx_frame_optionsを指定するために使用されます。
<frame>、<iframe>または<object>にページが埋め込まれることを許可するかどうかを指定し、クリックジャッキング攻撃を防ぎます。
一般的な値は:
DENY:このページはどのページからも埋め込み不可です。SAMEORIGIN:このページは同じオリジンのページからのみ埋め込み可能です。ALLOW-FROM uri:このページは指定されたURIからのみ埋め込み可能です(あまり使用されません)。
2.urls.py
re_path(regex, view, kwargs=None, name=None)
-
regex:URLパスを一致させるために使用される正規表現です。 -
views:このURLを処理するビュー関数です。 -
kwargs: オプションの辞書で、ビュー関数に追加のキーワード引数を渡すために使用されます。これらの引数はURLキャプチャされた引数とともにビュー関数に渡されます。 -
name=' ':URLパターンの名前で、URLの逆引きに使用されます。re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive, name='year_archive')-
テンプレートで
<a href="{% url 'year_archive' year=2023 %}">2023 Articles</a> -
ビューで
from django.urls import reverse def some_view(request): url = reverse('year_archive', args=[2023]) return redirect(url)reverse関数を使用してURLを生成し、redirect関数を使用してリダイレクトします。
-
3. models.py
4. urls.py
よく使う関数
-
render()
from django.shortcuts import render def home_view(request): context = { 'title': 'Home Page', 'message': 'Welcome to our website!', } return render(request, 'home.html', context)requestは現在のHTTPリクエストオブジェクトです。'home.html'はレンダリングするテンプレートファイルの名前です。contextは2つのキー値ペアを含む辞書:'title'と'message'です。これらのデータはテンプレートで使用できます。
home.html
<html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ message }}</h1> </body> </html>このテンプレートでは、
{{ title }}と{{ message }}はそれぞれ'Home Page'と'Welcome to our website!'に置き換えられます。 -
redirect()
redirect関数を使用してリダイレクトしますfrom django.shortcuts import redirect def my_view(request): # 別のビューにリダイレクト return redirect('another_view') def another_view(request): # 別のビューのロジックを処理 return render(request, 'another_template.html')外部URLへのリダイレクト
from django.shortcuts import redirect def my_view(request): # 外部URLにリダイレクト return redirect('https://www.example.com')パラメータを渡しながらリダイレクト
from django.shortcuts import redirect def my_view(request): # パラメータを渡して別のビューにリダイレクト return redirect('another_view', param1='value1', param2='value2')