※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。


【Django2】レコードをランダムに取得する方法と注意点

Django2 web開発 python3 Django サーバー開発

投稿日:2020年10月24日

このエントリーをはてなブックマークに追加
Djangoにはランダムにレコードを取得する方法が用意されています。 この方法を知っていると意外と役に立つ場面が多いので使い方と注意点についてメモしておきます。

はじめに

Djangoにはランダムにレコードを取得する方法が用意されています。

この方法を知っていると意外と役に立つ場面が多いので使い方と注意点についてメモしておきます。


order_by()

DjangoのQuerySetクラスのorder_by()関数は指定されたフィールドの値ごとに並び替えるQuerySetを取得します。

QuestionMark

order_by()に渡す引数として?を指定することでランダムなQuerySetを取得することができます。

例えばBlogPageというdjango.db.models.Modelを継承したModelクラスがあったとすると以下のような記述でランダムに並んだレコードを取得できます。

pages = BlogPage.objects.order_by("?")

ランダムなレコード取得は非常に便利なのですが、2つほど注意する点があります。

以下にその注意点について解説しておきます。

ランダムなレコードの取得が評価されるタイミング

ランダムなレコードの並び変えのQuerySetの評価タイミングについて少し注意しなければいけません。例えば以下のようなスクリプトを作成するとします。

sample.py
from blog.models import BlogPage

pages = BlogPage.objects.order_by("?")[:10]
print(pages[0].id == pages[0].id)

「何言ってるんや?wwwこいつ?www」

って感じのスクリプトです。

Trueが返されるに決まってるわwww逝ってよしwww」

と思うかもしれません。

しかし、実際に実行してみると...

ターミナル
$ python manage.py shell < sample.py
False

以外にも!

結果はFalseになりました!

実はQuerySetの並び替えは値の取得のたびに評価されるのです。

これを理解していないと、DBへの無駄なクエリの生成や、思わぬバグを生み出す原因になってしまいます!

解決方法は以外と簡単でQuerySet型から配列にキャストしてあげれば良いだけです!

sample.py
from blog.models import BlogPage

pages = BlogPage.objects.order_by("?")[:10]

pages = list(pages)    # 配列にキャスト

print(pages[0].id == pages[0].id)
ターミナル
$ python manage.py shell < sample.py
False

ランダムなレコードの取得をする際には、この挙動について常に気を向けておくべきですね。


参考書籍

このエントリーをはてなブックマークに追加


関連記事

記事へのコメント