中級向け

get_next_by_FOO, get_previous_by_FOO

Djangoにはあまり目立たない機能だけどとっても便利な機能というのがあります。

そのひとつが、このget_next_by_FOOget_previous_by_FOOです。

もちろん、FOOの部分は別の言葉が入ります。

これはモデルから生成されたオブジェクトに自動で生えてくる(実装される)メソッドなのですが、ある特定のフィールドを元に隣のレコード(オブジェクト)を取得することが出来るメソッドです。
FOOはフィールド名が入り、フィールドの並び順で隣のオブジェクトが決まります。
従って、このフィールドは数値型に準ずる型でなければなりません。

言い方を変えれば、普段はget_next_by_idget_previous_by_idで値を取得していると言えます。
フィールドはIDで、並び順が決まる数値型なので隣のオブジェクトを取得できます。

しかし現場ではいろいろありますよね。

もう少し条件を付与したいとか、数値型でソートしてないぜ、など多種多様な要件があると思います。

そういったときは独自のメソッドをモデルに定義します。

※ サンプルコードなので、実際には意味が無いとか効率悪いなどあると思います

class Post(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
    is_publish = models.BooleanField(defautl=False)
    created_at = models.DateTimeField(auto_add=True)
    # ... いろいろ定義

このような定義があったとします。簡単のため、かなりはしょっています。

ここに、タイトルと著者の二つの情報をつかって隣のレコードを取得したいときを考えてみます。

def get_next_by_title_and_author(self):
    return type(self).objects.filter(
        is_publish==True,  # 公開されている記事
        author='Dai',  # 著者を特定(簡単のため決め打ち)
        created_at__gt=self.created_at  # 自身よりも後に公開された情報である
    ).order_by(["created_at"]).first()

このようにクエリセットを作成して、並べ替えの最初の記事を取得すれば次の記事が取得できます。
クエリセット次第でいかなる値も取得可能です。

注意する必要があるのは、並べ替えに自分の情報が入ってしまうことがあることです。
今回はcreated_atgtにしているため自身はクエリされませんが、取得したオブジェクトでリンクを作成したらループした、ということもあります。
自身をexcludeするなり、上記のようにクエリ条件から外すなりして対策してください。

-中級向け