🌊
DjangoのORMで子テーブルのカラムを使ってfilterする
書くこと
- distinctを使ってフィルターする方法
- annotateを使ってフィルターする方法
利用技術
- Django
想定
モデル
以下のArticleとCommentモデルがあるとする。
class Article(models.Model):
title = models.CharField(max_length=100)
# (省略)
class Comment(models.Model):
text = models.CharField(max_length=100)
active = models.BooleanField(default=True)
# Article 1-* Comment
article = models.ForeignKey(
"Article",
models.PROTECT,
related_name="comments",
)
# (省略)
シチュエーション
1件以上のactiveなCommentと紐づくArticleを取得したい
方法論
distinctを使ってフィルターする方法
-
子テーブル__columns
でフィルターする - left outer joinしているため、
distinct()
する
return Article.objects.filter(
comments__active=True
).distinct()
left outer joinをするため、distinct()
をすることで期待通りの値を取得可能
annotateを使ってフィルターする方法
- articleにannotateを使ってBool型の
has_comments
カラムを付与する -
has_comments
でfilterする
article = Article.objects.annotate(
comment_count=Count(
"comments",
filter=(comments__active=True)
)
).annotate(
has_comments=Case(
When(comment_count__gt=0, then=True),
default=False,
output_field=BooleanField()
)
)
return article.filter(has_comments=True, )
Discussion