Feedjack 読む (4)

どこを辿って今どこにいるか分からなくなったのでまず整理。
今は fjlib.get_paginator 手続きの中。呼び出しの階層としては

  • views.mainview
    • fjlib.page_context
      • fjlib.get_paginator

なカンジ。一瞬 get_paginator を飛ばしかけて中に入ったのか。ログも結構滅茶苦茶だし。

とりあえず get_paginator の続き

以下のあたりが中断点か

    if site.order_posts_by == 2:
        localposts = localposts.order_by('-date_created', '-date_modified')
    else:
        localposts = localposts.order_by('-date_modified')

Site の order_posts_by という列の値で並び順を云々しているように読める。ちなみに models.py における列の定義は以下のような形になっている。

    order_posts_by = models.IntegerField(_('order posts by'), default=1, \
      choices=SITE_ORDERBY_CHOICES)

デフォは 1 との事。データベース API リファレンスによれば "-" が付いたら降順との事なので日付が新しい順に並ぶ、という事になりますな。
で、以降は後始末。

    paginator = ObjectPaginator(localposts.select_related(), \
      site.posts_per_page)
    try:
        object_list = paginator.get_page(page)
    except InvalidPage:
        if page == 0:
            object_list = []
        else:
            raise Http404
    return (paginator, object_list)

おそらくは

  • ObjectPaginator なオブジェクトを select_related された Post なオブジェクトとページごとのポストの数 (これは Site の属性) を元に生成
  • page で指定されたオブジェクトの並びを object_list に格納
  • 例外処理

を経て paginator と object_list を戻す、という事ですか。

戻り

get_paginator 手続きの呼び出しと object_list の状態による処理の振り分けが以下

    paginator, object_list = get_paginator(site, sfeeds_ids, \
      page=page, tag=tag, user=user_id)
    if object_list:
        # This will hit the DB once per page instead of once for every post in
        # a page. To take advantage of this the template designer must call
        # the qtags property in every item, instead of the default tags
        # property.
        user_obj, tag_obj = get_posts_tags(object_list, sfeeds_obj, \
          user_id, tag)
    else:
        user_obj, tag_obj = None, None

ええと、とりあえず真偽な式はブール演算 (bool operation)によれば

  • None
  • 0
  • 空のシーケンス(文字列、tuple、リスト)
  • 空のマップ型(辞書)

は偽と見るとの事。で、object_list が真判定であれば get_posts_tags 手続きを呼び出している。引数は

  • object_list (これは表示対象の Post なクエリセット?)
  • sfeeds_ids (Site からたぐれる Subscriber のクレリセット)
  • user_id (引数として page_context 手続きに渡される)
  • tag (引数として page_context 手続きに渡される)

の4つ。そろそろモデルのリレーションがきちんとイメージできてないと苦しそう。

続き

ぼちぼち進める事に。とりあえず Readingl Gauche 方面は明日がっつりヤる予定。で、続きは fjlib.get_posts_tags なんですが何故にこんなコトしてるのか、と言いつつ models.py を見てみると

    tags = models.Tag.objects.extra(\
      select={'post_id':'%s.%s' % (\
        connection.ops.quote_name('feedjack_post_tags'), \
        connection.ops.quote_name('post_id'))}, \
      tables=['feedjack_post_tags'], \
      where=[\
        '%s.%s=%s.%s' % (\
          connection.ops.quote_name('feedjack_tag'), \
          connection.ops.quote_name('id'), \
          connection.ops.quote_name('feedjack_post_tags'), \
          connection.ops.quote_name('tag_id')), \
        '%s.%s IN (%s)' % (\
          connection.ops.quote_name('feedjack_post_tags'), \
          connection.ops.quote_name('post_id'), \
          ', '.join([str(post.id) for post in object_list]))])

ええと字面で見るに Tag な行を extra で取得、となるのか。なんで非推奨な extra 使ってるのだろうか、と思い models.py 見てみたら無いし (> feedjack_post_tags にあたるモデル)。そりゃこうするしか無いわな。
おそらくベースで SQL に直してみるとこんな感じ??

select feedjack_post_tags.post_id 
 from feedjack_tag, feedjack_post_tags
 where feedjack_tag.id = feedjack_post_tags.tag_id
  and  feedjack_post_tags.post_id IN (... object_list の post.id のリスト);

日本語にできん (駄目
ってかこれ、違うな。

select feedjack_tag.*, feedjack_post_tags.post_id

みたいなカンジなのかなぁ。こっちが当たりっぽい。ちょっと今日は限界です。なんか進捗悪い今日この頃です。