LoginSignup
3
0

More than 1 year has passed since last update.

Django+Reactで学ぶプログラミング基礎(10): Djangoチュートリアル(投票アプリその5-1)

Last updated at Posted at 2022-06-08
[前回] Django+Reactで学ぶプログラミング基礎(9): Djangoチュートリアル(投票アプリその4-2)

はじめに

Django公式チュートリアル、その5-1です。
前回は、アプリを汎用ビューに書き換えました。
今回は、アプリのテストフェーズに入ります。

Djangoアプリ作成(その5-1): 投票(poll)アプリ

今回の内容

  • Python対話シェルで、APIを使用し動作確認

Djangoが提供するAPIで遊んでみる

チュートリアル その2の内容をここに移動しました。

  • Python対話シェルを起動し、Djangoが提供するAPIの動作確認
    • Pythonをmanage.py経由で実行する理由
      • manage.pyに設定されているDJANGO_SETTINGS_MODULE環境変数を使用するため
C:\kanban\pollsite>..\venv\.venv\Scripts\activate
(venv) C:\kanban\pollsite>python manage.py shell

image.png

  • モデルクラス二つをインポート
>>> from polls.models import Choice, Question
  • 質問事項のリストを確認
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question 
object (3)>, <Question: Question object (4)>, <Question: Question object (5)>, <Question: Question object (6)>]>
  • 新しい質問を作成し、保存
    • デフォルトでタイムゾーンが有効になっている
      • pub_dateフィールドにはdatetime with tzinfoデータ型を指定
      • timezone.now()関数を使用し、現在時刻を取得(datetime.datetime.now()関数ではなく)
>>> from django.utils import timezone
>>> q = Question(question_text="気持ちはいかがでしょうか?", pub_date=timezone.now())
>>> q.save()
  • 質問IDを確認
>>> q.id
7
  • Python属性を使用し、モデルフィールド値にアクセス
>>> q.question_text
'気持ちはいかがでしょうか?'
>>> q.pub_date
datetime.datetime(2022, 6, 7, 23, 20, 34, 394580, tzinfo=datetime.timezone.utc)
  • 属性を変更することで、フィールド値を変更し、保存
>>> q.question_text = "今日の予定は?"
>>> q.save()
  • 質問事項に新しい質問が追加されたことを確認
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question 
object (3)>, <Question: Question object (4)>, <Question: Question object (5)>, <Question: Question object (6)>, <Question: Question object (7)>]>
  • 質問オブジェクトの表現をわかりやすく修正
    • <Question: Question object (1)>のような表現は可読性がない
    • QuestionモデルとChoiceモデルに__str__()メソッドを追加
    • __str__()メソッドによるオブジェクト表現は
      • Django自動生成の管理サイトでも使用される(対話シェルだけでなく)
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

image.png

  • モデルクラスにクラスメソッドを追加
    • 以下2点参照するためインポート
      • Python標準モジュールdatetimeをインポート
      • Djangoタイムゾーン関連ユーティリティdjango.utils.timezoneをインポート
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)
  • polls/models.pyの変更を保存
  • 新しいPython対話シェルを始める
>>> exit()

(venv) C:\kanban\pollsite>python manage.py shell
>>> from polls.models import Choice, Question
  • __str__()メソッドが機能するか確認
>>> Question.objects.all()
<QuerySet [<Question: Djangoは難しいですか>, <Question: 難しいポイントは?>, <Question: 趣味は?>, <Question: 目標は?>, <Question: 幸せとは?>, <Question: 楽しいことは?>, <Question: 今日の予定は?>]>
  • 検索APIで検索
    • Djangoは、キーワード引数によって駆動される検索APIを提供
>>> Question.objects.filter(id=1)
<QuerySet [<Question: Djangoは難しいですか>]>
>>> Question.objects.filter(question_text__startswith='Django')
<QuerySet [<Question: Djangoは難しいですか>]>
  • 今年に公開された質問一覧を取得
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.filter(pub_date__year=current_year) 
<QuerySet [<Question: Djangoは難しいですか>, <Question: 難しいポイントは?>, <Question: 趣味は?>, <Question: 目標は?>, <Question: 幸せとは?>, <Question: 楽しいことは?>, <Question: 今日の予定は?>]>
  • 存在しないIDをリクエストすると、例外発生
>>> Question.objects.get(id=10)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\kanban\venv\.venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\kanban\venv\.venv\lib\site-packages\django\db\models\query.py", line 496, in get
    raise self.model.DoesNotExist(
polls.models.Question.DoesNotExist: Question matching query does not exist.
  • 主キーによる検索には、ショートカットpkを使用
    • 以下は`Question.objects.get(id=1)と同じ
>>> Question.objects.get(pk=1)
<Question: Djangoは難しいですか>
  • 上記追加した、カスタムメソッドwas_published_recentlyが機能するか確認
>>> q = Question.objects.get(pk=7) 
>>> q.was_published_recently()     
True
  • 質問にいくつかの選択肢を与える
>>> q = Question.objects.get(pk=7)
  • 質問に紐づく選択肢セットを確認、存在しない
>>> q.choice_set.all()
<QuerySet []>
  • 選択肢を三つ作成
>>> q.choice_set.create(choice_text='はい', votes=0)
<Choice: はい>
>>> q.choice_set.create(choice_text='いいえ', votes=0)
<Choice: いいえ>
>>> c = q.choice_set.create(choice_text='どちらでもない', votes=0)
  • Choiceオブジェクトから、関連するQuestionオブジェクトにAPIでアクセス可能
>>> c.question
<Question: 今日の予定は?>
  • Questionオブジェクトから、関連するChoiceオブジェクトにAPIでアクセス可能
>>> q.choice_set.all()
<QuerySet [<Choice: はい>, <Choice: いいえ>, <Choice: どちらでもない>]>
>>> q.choice_set.count()
3
  • APIで、検索キーワード引数の形式
    • field__lookuptype=value
      • 区切り文字は、二重下線
    • 例えば、pub_dateフィールドが今年となっている質問のすべての選択肢を検索
      • question__pub_date__year
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: 難しい>, <Choice: 難しくない>, <Choice: 旅行>, <Choice: 課題解決>, <Choice: 趣味>, <Choice: はい>, <Choice: いいえ>, <Choice: どちらでもない>]>
  • 選択肢を削除
>>> c = q.choice_set.filter(choice_text__startswith='どちらでもない')
>>> c.delete()
(1, {'polls.Choice': 1})

おわりに

Djangoが提供するAPIを使用し、モデル操作や確認を行ってみました。
次回も続きます。お楽しみに。

[次回] Django+Reactで学ぶプログラミング基礎(11): Djangoチュートリアル(投票アプリその5-2)
3
0
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
3
0