0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Django][個人的メモ]: 外部キーに紐付けされたデータの件数をfilter処理に使う方法

Posted at

前置き

Djangoチュートリアルを終えてちまちまと自分用にカスタマイズしているくらいの初心者です。その過程で自動テストを追加しようとチュートリアルを再度確認していると、以下のような記述が。

テストを追加することによって、同じように他の方法でアプリを改善できるでしょう。例えば、Choices を一つも持たない馬鹿げた Questions が公開可能になっています。このような Questions を排除するようビューでチェックできます。 Choices がない Question を作成し、それが公開されないことをテストし、同じようにして、Choices がある Question を作成し、それが公開 される ことをテストすることになるでしょう。
(引用元:さらなるテストについて考える)

自分は英単語と日本語を1:Mで対応させたモデルを使っているので、"対応する日本語を一つも持たない馬鹿げた英単語が公開可能になっている"状態です。

その手の表示を弾きたいだけなら、htmlファイル側でテンプレートタグを使い、適当なif処理でもさせればよいです。が、今回は公式のテストでも利用されているassertQuerysetEqualを使いたかった、というより他のテスト手法がわからなかったので、view側でQuerysetを送信する段階で弾くことにしました。

参考サイト様

Djangoで、集計処理

コード

models.py
class EnglishWord(models.Model):
    spell = models.CharField(max_length=30)
    pub_date = models.DateTimeField('date published')
    difficulty = models.IntegerField(default=0)

    def __str__(self):
        return self.spell
    
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published Recently?'


class JapaneseWord(models.Model):
    english_word = models.ForeignKey(EnglishWord, on_delete=models.CASCADE)
    japanese_mean = models.CharField(max_length=50)
    difficulty = models.IntegerField(default=0)

    def __str__(self):
        return self.japanese_mean

views.py
from django.db.models import Count

class IndexView(generic.ListView):
    template_name = 'wordapp/index.html'
    context_object_name = 'latest_english_word_list'

    def get_queryset(self):
        return EnglishWord.objects.annotate(count=Count('japaneseword')).filter(count__gt=0)

annotateで臨時のカラムを設けて、そこにカウントした件数を格納し、格納した件数で条件を設定する、といった感じだと思います。あとは後ろにチュートリアルどおりにorder_byを付け加えるなりなんなりできそうです。

終わりに

多分SQLを含めたデータ処理に慣れている人にとっては当たり前の話なのでしょうが、3時間ほど詰まったので備忘録代わりに。もっと上手いやり方がありそうな気配がしますが、とりあえず希望通りに動いたのでヨシ。集合知に感謝。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?