1. TOP
  2. ブログ
  3. Django SQL データベース 操作 まとめ 入門(3)order_by、values

Django SQL データベース 操作 まとめ 入門(3)order_by、values

更新日:2021年2月1日
Djangoで、モデルで定義したデータベースのテーブルからデータを取得したり操作したりする方法をDjangoの公式ドキュメントを参考にして、記載しています。order_by、valuesについてまとめています。

環境:Python3.8.2 Django3.1.5

order_by(*fields)

models.py例
Entry.objects.filter( pub_date__year=2005 ).order_by( '-pub_date', 'headline' )

上記は、pub_date 降順(DESC), headline 昇順(ASC)の例です。

降順(DESC)はreverse()でできますが、order_by()で降順(DESC)にしたいフィールドに -を付けるだけで簡単に指定できます。

values(*fields, **expressions)

# This list contains a Blog object.
>>> Blog.objects.filter( name__startswith='Beatles' )
<QuerySet [<Blog: Beatles Blog>]>

# This list contains a dictionary.
>>> Blog.objects.filter( name__startswith='Beatles' ).values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

values()に取得したいフィールドを指定してそのフィールドのデータを取得できますが、指定しない場合は上記のように全フィールドの辞書データが取得できます。

全フィールドの場合は、上記のようにvalues()を指定しなくてもBeatles Blogの辞書データで取得できます。

>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

上記のように、フィールドを指定('id', 'name')した場合は、そのフィールドのデータのみ取得できます。

values()の引数にオプション追加 **expressions

>>> from django.db.models.functions import Lower
>>> Blog.objects.values( lower_name=Lower('name') )
<QuerySet [{'lower_name': 'beatles blog'}]>

上記のようにLower()を追加する事により、'Beatles Blog'→'beatles blog'小文字 にしたデータを取得できます。

グループ化して集計数取得

>>> from django.db.models import Count
>>> Blog.objects.values( 'entry__authors', entries=Count('entry') )
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>

>>> Blog.objects.values( 'entry__authors' ).annotate( entries=Count( 'entry' ) )
<QuerySet [{'entry__authors': 1, 'entries': 33}]>

上記のように entryとauthorsモデルを結合して、集計数count()を求める場合は、
先にグループ化annotate()を追加してから、集計数Count('entry')を取得します。

外部キーのデータ取得

>>> Blog.objects.values( 'name', 'entry__headline' )
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>

OneToOneField、 ForeignKey、またはManyToManyField 属性のデータは
上記のように指定すれば 結合してそのデータを取得できます。

values_list(*fields, flat=False, named=False)

辞書データでなく、リストで値のみ取得する場合はvalues_list()を使用して下さい。
引数のフィールドは、表示したい順('id', 'headline')に記載します。

>>> Entry.objects.values_list( 'id', 'headline' )
<QuerySet [( 1, 'First entry' ), ...]>

>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list( 'id', Lower( 'headline' ) )
<QuerySet [( 1, 'first entry' ), ...]>

values_list()、flat=True

単一フィールドの場合は、下記のようにflat=Trueを指定すれば、結果をシングル値で取得できます。

>>> Entry.objects.values_list( 'id' ).order_by( 'id' )
<QuerySet[(1,), (2,), (3,), ...]>

>>> Entry.objects.values_list( 'id', flat=True ).order_by( 'id' )
<QuerySet [1, 2, 3, ...]>

values_list()、named=True

named=Trueを指定すれば、下記のように結果をPythonのnamedtuple()として取得できます。

>>> Entry.objects.values_list( 'id', 'headline', named=True )
<QuerySet [Row(id=1, headline='First entry'), ...]>

values_list()、特定のフィールド値1件取得

特定のフィールドの値を1件のみ取得する場合は、values_list()にget()を続けます。

>>> Entry.objects.values_list( 'headline', flat=True ).get( pk=1 )
'First entry'


B!

前の記事:Django SQL データベース 操作 まとめ 入門(2)where条件 filter(),exclude(),Qオブジェクト

次の記事:Django SQL データベース 操作 まとめ 入門(4)Where条件、演算子、LIKE