naritoブログ

このブログはPython/DjangoとBootstrap4で作成されました
Githubのソースコード

Djangoで、記事を公開順に表示する

約230日前 2017年12月29日4:00
プログラミング関連
Django Python
例えば、以下のようなモデルがあったとします。
タイトル、本文、作成日、そして、公開フラグを持ったモデルです。
ブログの記事には下書きという状態があり、本公開したい場合に、is_publicをTrueにすることにします。
from django.db import models
from django.utils import timezone


class Post(models.Model):
    """ブログの記事"""
 
    title = models.CharField('タイトル', max_length=255)
    text = models.TextField('本文')
    is_publick = models.BooleanField('公開フラグ', default=False)
    created_at = models.DateTimeField('作成日', default=timezone.now)
 
    def __str__(self):
        return self.title



views.pyでの一覧表示は、以下のようになります。
単純にfilterで、公開フラグがTrueのものだけ取得します。
from django.views import generic
from .models import Post


class IndexView(generic.ListView):
    model = Post

    def get_queryset(self):
        # 公開フラグがTrueで、作成日順に並び替え
        return super().get_queryset().filter(is_publick=True).order_by('-created_at')
        




では本題です。現在は作成日順に並び替えていますが、これを記事の公開日順にしたいとすると、どのように書けるでしょうか。
models.pyを以下のようにします。
from django.db import models
from django.utils import timezone


class Post(models.Model):
    """ブログの記事"""
 
    title = models.CharField('タイトル', max_length=255)
    text = models.TextField('本文')
    is_publick = models.BooleanField('公開フラグ', default=False)
    publick_at = models.DateTimeField('公開日', blank=True, null=True)  # これが増えた
    created_at = models.DateTimeField('作成日', default=timezone.now)
 
    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        # is_publicがTrueで、publick_atがNoneのとき...
        # つまり、is_publickをTrueにした初回のみここです
        if self.is_publick and not self.publick_at:
            self.publick_at = timezone.now()
        super().save(*args, **kwargs)




増えたのは、publick_atというDateTimeFieldです。blank=True、null=Trueにしておきます。
そして、saveメソッドを上書きします。is_publickをTrueにした初回だけ、publick_atに現在日付を入れるのです。

後は、views.pyで公開日順に並び替えるだけです。
from django.views import generic
from .models import Post


class IndexView(generic.ListView):
    model = Post

    def get_queryset(self):
        # 公開フラグがTrueで、publick_at順に並び替え
        return super().get_queryset().filter(is_publick=True).order_by('-publick_at')