querysetでextraを使って新たに定義したものについてorder_byする方法
今回はDjangoのquerysetでextraを使って新たに定義したものについてorder_byする方法についてご紹介いたします。
querysetでextraを使って新たに定義したものについてorder_byする方法
最初に結論を言ってしまうと、以下のソースを使うことでquerysetでextraを使って新たに定義したものについて昇順で整列させることができます。
1 2 3 4 5 6 |
ratings_tuples = [(r.id, 'extraで新たに定義した変数') for r in instances] ratings_list = sorted(ratings_tuples, key=lambda x: x[1]) pk_list = [idx for idx, rating in ratings_list] from django.db.models import Case, When preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)]) instances = instances.filter(pk__in=pk_list).order_by(preserved) |
例として次のBookモデルがあるとします。
1 2 3 4 5 6 7 |
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=120) # max_length=required author = models.CharField(max_length=120) # max_length=required price = models.DecimalField(decimal_places=2, max_digits=100) |
今Bookオブジェクトは3つあり、それぞれ保持する値は次の通りだとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
>>> instances = Book.objects.all() >>> for a in instances: ... a.title ... a.author ... a.price ... 'title1' 'author1' Decimal('400.00') 'title2' 'author2' Decimal('100.00') 'title3' 'author3' Decimal('500.00') |
Bookモデルに関して、extraを使って新たに税込みの値段を表す’taxPrice’を定義するとします。
extraを使ってpriceに10パーセントの税率をかけたtaxPriceを新たに定義します。
1 |
Book.objects.extra(select={'taxPrice': 'price * 1.1'}) |
このtaxPriceでソートをかけたいとします。(taxPriceを使わずともそのままpriceでソートをかければ同じ結果になりますが、あくまでも例です。)
冒頭のソースをいじって、次のソースを準備します。
1 2 3 4 5 6 |
ratings_tuples = [(r.id, r.taxPrice) for r in instances] ratings_list = sorted(ratings_tuples, key=lambda x: x[1]) pk_list = [idx for idx, rating in ratings_list] from django.db.models import Case, When preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)]) instances = instances.filter(pk__in=pk_list).order_by(preserved) |
上記ソースを実行すると次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
>>> instances = Book.objects.extra(select={'taxPrice': 'price * 1.1'}) >>> ratings_tuples = [(r.id, r.taxPrice) for r in instances] >>> ratings_list = sorted(ratings_tuples, key=lambda x: x[1]) >>> pk_list = [idx for idx, rating in ratings_list] >>> from django.db.models import Case, When >>> preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)]) >>> instances = instances.filter(pk__in=pk_list).order_by(preserved) >>> instances <QuerySet [<Book: Book object (2)>, <Book: Book object (1)>, <Book: Book object (3)>]> >>> for a in instances: ... a.taxPrice ... 110.00000000000001 440.00000000000006 550.0 |
長くなってしまうのでソースの解説はしません。
対話型シェルで1行ずつ実行結果を探ればどういうロジックなのかが分かると思います。
終わりに
今回はDjangoのquerysetでextraを使って新たに定義したものについてorder_byする方法についてご紹介いたしました。
ディスカッション
コメント一覧
まだ、コメントがありません