12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【解説付き】Django チュートリアル その2 -後編-

Last updated at Posted at 2019-08-22

はじめに

これは、【解説付き】Django チュートリアル その2 -前編-に続き、
はじめての Django アプリ作成、その2の後半部分に解説をつけて初学者にわかりやすく学んでいただきたいというためのものです。

その2は、ボリュームがあるため前編/後編とさせていただいております。

前編はこちら

対象

  • pythonはなんとなくわかってるけど、djangoを覚えたい
  • 業務でdjango触ってたけど、きちんと理解したい

上記の方々を対象としています。
環境は、Macを使用して進めていきますので、Windowsユーザーの方は、Windows環境に読み替えてついてきていただければと思います。

目次

API で遊んでみる

Python 対話シェルを起動して、 Django が提供する API で遊んでみましょう。

と、チュートリアルでは突発的にこんな事を言ってきます。

Python対話シェルAPI といきなり言われてもわからないですよね。

API

APIとは、Application Programming Interfaceの略です。
「アプリケーションプログラムとの、コミュニケーションを行うもの」という解釈になるかと思います。

プログラムとお話する痛いヤツと思われそうですが、今回のケースでいうと、
「djangoの機能を、対話的に実行するための手段」
となります。

なんとなく、イメージが付きやすくなってきたと思います。

※ APIには、WEB APIというものもあります(一般的にこちらを指すことが多い)
これについては、APIを作る解説として、改めて記事化しようと思います。

Python対話シェル

Python対話シェルとは、pythonが提供するAPIです。

Python シェルを起動するには、以下のコマンドを実行します

$ python manage.py shell

python コマンドから、 manage.py を実行することで djangoと接続できます。

djangoの対話シェルに入ったら データベースのAPIを触ってみましょう

managepy.gif

上の内容をテキスト化したもの(クリックすると表示されます)
# pollsのmodelsファイルから、Choice, Questionを読み込む
>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# Questionの全データを取得する(現時点では0件)
>>> Question.objects.all()
<QuerySet []>

# djangoのutileファイルから、timzeoneを読み込む
>>> from django.utils import timezone
# Questionクラスのインスタンスを作る。
# question_textに"What's new?"、pub_dateに、現在エリアの現在時刻を指定
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# インスタンスのsave()メソッドを実行し、DBに保存
>>> q.save()

# DBに保存されることで、IDが採番される
>>> q.id
1

# インスタンスのフィールドの値を確認
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# question_textを"What's up?"に変更
>>> q.question_text = "What's up?"
# .save()を行うことで、変更内容がDBに反映される
>>> q.save()

# データが入ったので、改めて、全件取得を実行してみる
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

取得したデータが、
<Question: Question object (1)>と表示されてますよね
この状態では、どんなデータかわからないため、
polls/models.pyQuestion モデルを編集しましょう。
__str__() メソッドを QuestionChoice に追加します。

polls/models.py
from django.db import models

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

__str__()を書くことで、対話シェルでの見栄えだけではなく、Djangoで自動生成されるadmin(管理画面)の
一覧データ表示時にも使用されます。
モデルには、__str__() メソッドをつけるようにしましょう。

デモ用にカスタムのメソッドを追加してみましょう

polls/models.py
import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

import datetimefrom django.utils import timezone を追加しました。
これは、 Python の 標準モジュール datetime と Django のタイムゾーン関連ユーティリティの django.utils.timezone を利用するために呼び出しています。
Python でのタイムゾーンのついて詳しく知りたい方は、タイムゾーンサポートドキュメント を参照してください。

もう一度 python manage.py shell を実行して確認してみましょう。
(ソースを変更した場合、対話モードを開き直さないと、変更が反映されないので気をつけてください)

managepy2.gif

上の内容をテキスト化したもの(クリックすると表示されます)

>>> from polls.models import Choice, Question

# __str__()を追加したことで、オブジェクトがわかりやすくなりました。
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# データベースから条件でフィルターして(絞り込んで)取得することができます。
# .all() を filter(id=1) と変えることで、IDが1のものを取得してくれます。
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
# filter(question_text__startswith='What') と変えることで、Whatから始まるデータを取得してくれます。
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Questionのpub_dateを今年のデータを指定します
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# .get(id=2)を指定すると、条件とマッチする1件を取得します。
# データがない場合や、複数件がhitするような指定の場合は、エラーとなります。
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

モデルのリレーションについてはリレーション先オブジェクトにアクセスする を参照してください。
API を通じた、フィールドルックアップのためのダブルアンダースコアの使い方は フィールドルックアップ を参照してください。
データーベース API の詳細は データベース API リファレンス を参照してください。

Django Adminの紹介

設計思想

コンテンツの追加や変更、削除を行うための管理サイトを作ることはクリエイティブではなく、面倒に感じられることが多いと思います。
そのため、Djangoはモデル(データ)のための管理インタフェースを自動的に生成してくれます。

もともとDjangoは、ニュース系のサイトを管理する目的で開発されました。
ニュース系のサイトでは、 「コンテンツの作成者 (content publisher)」と「公開 (public) 」サイトを明確に区別しています。
サイトの管理者は、新たな話題やイベント、 スポーツのスコアなどの入力にシステムを使い、コンテンツは公開用サイト上で表示されます。
Django は、サイト管理者向けのadmin(管理)機能を提供しています。

admin はサイトの訪問者でなく、サイト管理者に使われることを意図しています。

管理ユーザーを作成する

最初に私達はadminサイトにログインできるユーザーを作成する必要があります。

下記のコマンドを実行します。

$ python manage.py createsuperuser

好きなユーザー名を入力しEnterを押してください。

Username: admin

emailアドレスを入力します。

Email address: admin@example.com

最後のステップはパスワードの入力です。
確認のために、パスワードの入力を2回求められます。

Password: **********
Password (again): *********
Superuser created successfully.

開発サーバーの起動

Django adminサイトはデフォルトで有効化されます。
開発サーバーを起動して触れてみましょう。

もしサーバーが起動していなかったら、このようにして起動しましょう

$ python manage.py runserver

次はブラウザで、http://127.0.0.1:8000/admin/ にアクセスします。
以下のような admin のログイ ン画面が表示されるはずです

admin01.png

translation がデフォルトで on になっているため、ログイン画面はあなたの言語で表示されるかもしれません。
これは、あなたのブラウザの設定と、 Django がその言語に翻訳されているかどうかによります。

admin サイトに入る

前のステップで作成したスーパーユーザーのアカウントでログインしてみましょう。
Django admin のインデックスページが表示されるはずです

admin02.png

groups と usersなどの編集可能なコンテンツが表示されるはずです。
これらは Django に含まれる認証フレームワーク django.contrib.auth によって提供されます。

Poll アプリを admin 上で編集できるようにする

polls アプリは管理画面に表示されていましたか?
admin のインデックスページを見ても表示されていませんね。

Question オブジェクトのadmin インタフェースをadminに追加する必要があります。
追加するために、polls/admin.py に下記のように編集しましょう

polls/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)

admin の機能を探究してみる

私たちが Question を追加したので、 Django は admin インデックスページに表示してくれました。

admin03t.png

Questions をクリックしましょう。
questions のための "change list" ページが表示されます。
このページにはデータベース中のすべての question が表示され、あなたはその中のひとつを選んで変更することができます。
ここには、上記で作成した "What's UP?" question もあります

admin04t.png

"What's up?" questionをクリックして編集してみましょう

admin05t.png

※下記日本語版
スクリーンショット 2019-08-22 21.02.43.png

以下の点に注意してください

  • 入力フォームは Question モデルから自動的に生成されます。
  • モデルのフィールドの型 (DateTimeField 、 CharField など) に応じて、HTML 入力フォームと対応しています。
  • DateTimeField は JavaScript ショートカットがついています。
    日付 (dates) のカラムには「今日 (today)」 へのショートカットとカレンダーポップアップボタンがあります。
    時刻 (times) には「現在 (now)」へのショートカットと、よく入力される時刻のリストを表示するポップアップボタンがあります。

ページの下部には下記のボタンが用意されています。

  • 保存 (Save) – 変更を保存して、このモデルの一覧のページに戻ります。
  • 保存して編集を続ける (Save and continue editing) – 変更を保存して、このオブジェクトの編集ページをリロードします。
  • 保存してもう一つ追加 (Save and add another) – 変更を保存して、新たに新規追加するための空の編集ページを表示します。
  • 削除 (Delete) – 削除確認ページを表示します。

もし「Date published」の値が、チュートリアルその1 で作成した questionと一致しないのであれば、TIME_ZONEの設定が漏れていた可能性があります。
設定を変更して、ページをリロードし、正しく表示されるか確認してください。

今日現在ショートカットをクリックして、「Date published」を変更してみましょう。
変更したら、「保存して編集を続ける」を押します。

次に、右上に ある「履歴 (History)」をクリックしてみましょう。
ユーザが管理サイト上でオブジェクトに対して行った変更履歴の全てを、変更時刻と変更を行ったユーザ名付きでリストにしたページが表示されます

admin06t.png

Modelの APIadmin サイトに慣れてきたら、 チュートリアルその3 を読んで、 polls アプリにビューをさらに追加する方法を学習しましょう。

次回予告

ここまでがdjango チュートリアルのその2 -後編- でした。

既にdjangoに触れてる人や、多言語に詳しい人ならわかるけど、初めての人にはわかりにくい部分が多いと思います。
本家のチュートリアルに補足情報を盛り込んだ形で記載しているので理解の手助けになれれば幸いです。

次回は、はじめての Django アプリ作成、その3について書いていこうと思います。

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?