もた日記

くだらないことを真面目にやる

Djangoメモ(5) : 対話型シェルでAPIを使ってみる

Python 3.6.4 Django 2.0.2

A Complete Beginner's Guide to Djangoのチュートリアルを参考にDjango が提供する APIを使ってみる。

対話型シェルの起動

前回まででモデルの作成は完了しているのでAPIでオブジェクトを作成してみる。 まずは下記コマンドで対話型シェルを起動する。

$ python manage.py shell

ドキュメントによるとpython manage.py shellと単なるpythonコマンドとの違いは下記とのこと。

なぜ単なる “python” コマンドではなく上記のコマンドを使うかというと、 manage.py が DJANGO_SETTINGS_MODULE 環境変数を設定してくれるからです。これにより、 Django に mysite/settings.py ファイルへの import パスが与えられます。

確かに単なるpythonコマンドでモデルをインポートしようとすると失敗してしまう。

>>> from boards.models import Board
 ...
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

なお、単なるpythonコマンドでもDjangoを使うようにするには以下のようにすればよいらしい(myprojectのところはプロジェクト名)

$ export DJANGO_SETTINGS_MODULE=myproject.settings
$ python
>>> import django
>>> django.setup()
>>> from boards.models import Board


APIでオブジェクト作成

対話型シェルを起動したら最初にモデルをインポートする。

>>> from boards.models import Board

新しいBoardオブジェクトの作成は以下のようにする。
この場合はsave()は明示的に呼ぶ必要があり、save()が成功すると自動的にidが振られる。
また、各フィールドにはboard.nameのようにアクセス可能。

>>> board = Board(name='Django', description='This is a board about Django.')
>>> board.save()
>>> board.id
1
>>> board.name
'Django'
>>> board.description
'This is a board about Django.'

フィールドの値を変更することもできる。

>>> board.description = 'Django discussion board.'
>>> board.save()
>>> board.description
'Django discussion board.'

また、オブジェクトの作成は以下のようにobjects.createでもできる。

>>> board = Board.objects.create(name='Python', description='General discussion about Python.')
>>> board.id
2
>>> board.name
'Python'
>>> board.description
'General discussion about Python.'

作成したオブジェクトはデータベースに反映されている。

sqlite> select * from boards_board;
1|Django|Django discussion board.
2|Python|General discussion about Python.


__str__()メソッド

先ほど登録したオブジェクトをall()で表示してみる。

>>> Board.objects.all()
<QuerySet [<Board: Board object (1)>, <Board: Board object (2)>]>

返り値はQuerySetと呼ばれるものだが<Board: Board object (1)>がオブジェクトの表現として役に立っていないのでBoardモデルに__str__()メソッドを追加して修正してみる。
exit()で対話型シェルを抜けてboards/models.py__str__()を追加する。

class Board(models.Model):
    name = models.CharField(max_length=30, unique=True)
    description = models.CharField(max_length=100)

    def __str__(self):
        return self.name

これでオブジェクトの表現が見やすくなる。ドキュメントによると__str__()メソッドを追加することは重要とのこと。

>>> Board.objects.all()
<QuerySet [<Board: Django>, <Board: Python>]>

あなた自身のインタラクティブシェルでの表示での利便性のためだけではなく、Djangoの自動生成adminでオブジェクトの表現として使用されるという理由からも __str__() メソッドをモデルに追加することは重要です。


その他のAPI

all()の返り値のQuerySetはリストのように取り扱うことができる。

>>> boards_list = Board.objects.all()
>>> for board in boards_list:
...     print(board.description)
...
Django discussion board.
General discussion about Python.

get()メソッドを使うとオブジェクトを1つだけ取得できる。

>>> django_board = Board.objects.get(id=1)
>>> django_board.name
'Django'

存在しないidを指定すると例外が投げられる。

>>> board = Board.objects.get(id=3)
boards.models.DoesNotExist: Board matching query does not exist.

get()メソッドは別のフィールを指定することもできる。

>>> Board.objects.get(name='Django')
<Board: Django>
>>> Board.objects.get(name='django')
boards.models.DoesNotExist: Board matching query does not exist.```


まとめ

  • python manage.py shellで対話型シェルを起動
  • board = Board()はオブジェクトを保存せずに作成
  • board.save()でオブジェクトを保存
  • Board.objects.create(name='...', description='...')はオブジェクトの作成&保存
  • Board.objects.all()で全オブジェクトを取得
  • Board.objects.get(id=1)で条件に一致したオブジェクトを取得

追記:対話型シェルを便利にしたい場合は下記記事を参照。

wonderwall.hatenablog.com