モデル (Model) - データアクセスの基礎
Django の Model (django.db.models.Model) のサブクラスとしてモデルを定義すると、 バックエンドのデータベースの操作を隠すことができます。
ここでは実際に、モデルの基礎 で作成したモデルを利用して、 Django のシェルからデータを操作しましょう。
シェルを開始する管理コマンドは次の通りです。
$ python manage.py shell
準備
コマンドラインから内容を確認しやすいように、モデルの基礎 で作成したモデル Company と Employee に __str__ メソッドを追加しておきます。
from django.db import models
class Company(models.Model):
name = models.CharField(max_length = 200)
website = models.URLField()
def __str__(self):
return self.name;
class Employee(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
firstname = models.CharField(max_length = 100)
lastname = models.CharField(max_length = 100)
email = models.EmailField()
def __str__(self):
return self.lastname;
この変更はバックエンドに関わらないので、migrate 管理コマンドは実行する必要はありません。
さて、それでは早速試してみましょう。
オブジェクトのクエリー
オブジェクトの作成
オブジェクトは save() または create を用いて作成できます。
$ python manage.py shell ... (InteractiveConsole) >>> from myapp1.models import Company, Employee >>> c = Company(name='Foo', website='http://foo.com/') >>> c.save() # これで作成される >>> Company.objects.create(name='Bar', website='http://bar.com/') <Company: Bar> # 作成結果。上の一行で作成 >>> Company.objects.all() # 全ての要素のリスト取得 <QuerySet [<Company: Foo>, <Company: Bar>]> >>>
確かに作成されていますね。
フィルタ - 条件に合ったオブジェクト・リストの取得
filter 関数で取得するオブジェクトの条件を指定できます。<属性>__contains を用いると、指定した属性に指定した値を含むオブジェクトのリストを取得できます。
>>> Company.objects.filter(name__contains='oo')
<QuerySet [<Company: Foo>]> # Foo がヒットしてます
ここでは、name という名前の属性を元にデータの抽出をしているので、name__contains というフィルタを設定しています。 _ は二つ並んでいることに注意してください。
__contains は大文字と小文字を区別します。区別しない場合は __icontains とします。
>>> Company.objects.filter(name__contains='f') <QuerySet []> # 大文字小文字区別するので結果セットは空 >>> Company.objects.filter(name__icontains='f') <QuerySet [<Company: Foo>]> # Foo がヒット
オブジェクトをひとつ取得
filter では結果はオブジェクトのリストとして返されます。 しかし、場合によってはひとつのオブジェクトだけが返ることを期待する場合もあります。 そのときは get を利用します。
>>> Company.objects.filter(name='Bar')
<QuerySet [<Company: Bar>]>
>>> Company.objects.get(name='Bar')
<Company: Bar> # 要素をひとつ取得するときは get メソッドが使える
get 関数では、フィルタの結果条件に一致するオブジェクトが複数あると次のように例外が発生します。
>>> Company.objects.get(website__contains='http') Traceback (most recent call last): File "<console>", line 1, in <module> ... myapp1.models.MultipleObjectsReturned: get() returned more than one Company -- it returned 2!
また、条件に一致するものが無い場合も次のように例外が発生します。
>>> Company.objects.get(name='Apple') Traceback (most recent call last): File "<console>", line 1, in <module> ... myapp1.models.DoesNotExist: Company matching query does not exist.
そういうわけなので、get 関数はプライマリキーでデータを引く状況のように基本的には確実にデータがあって、 存在しない場合は何らかの予測していないことが発生すべき、という場合に利用するべきでしょう。
結果のソート
オブジェクトをある条件で並べるには、order_by を利用します。
>>> Company.objects.order_by('name') # order_by で表示順を指定 <QuerySet [<Company: Bar>, <Company: Foo>]> >>> Company.objects.order_by('-name') # order_by - で逆の表示順 <QuerySet [<Company: Foo>, <Company: Bar>]>
filter で取得した結果リストに対しても、order_by は可能です。
>>> Company.objects.filter(name__contains='a').order_by('name') <QuerySet [<Company: Bar>]>
更新
オブジェクトの取得、属性の設定、save() とすることで、オブジェクトの属性を更新できます。
>>> c = Company.objects.get(name='Foo') >>> c <Company: Foo> >>> c.id 2 >>> c.name = 'Google' >>> c.save() >>> Company.objects.filter(name__contains='o') <QuerySet [<Company: Google>]>
オブジェクト取得後 update() を呼ぶことで、一行で更新可能です。
>>> Company.objects.filter(id=2).update(name='Goooogle') 1 >>> Company.objects.filter(name__contains='o') <QuerySet [<Company: Goooogle>]>
削除
削除も更新と同様の方法で、オブジェクト取得 delete() というステップで削除できます。
>>> c = Company.objects.filter(name__contains='o') >>> c.delete() (1, {'myapp1.Employee': 0, 'myapp1.Company': 1}) >>> Company.objects.all() <QuerySet [<Company: Bar>]>
以上、ここでは基本的なオブジェクトのクエリー方法・操作方法について説明しました。