Feedjack 読む (3)

昨晩ごたごたしつつ、微妙にハマッていたのが、新規に作ったユーザで管理サイトに login できぬ、というもの。今朝方、admin なユーザで追加したユーザに管理な権限をナニすれば良いんじゃね? という事に気づく。
で、帰宅して確認してみたらそうなっていた。どうやら昨晩ログインできなかった原因はパスワードを間違っていた模様。現時点では新規で追加したユーザに

を行なっている状態。feedjack なソレは多分シボる可能性もあり、かも。これで追加したユーザが feed を追加な i/f は作成可能、なのかな??

とりあえず views.mainview を掘ってみる。とりあえず微妙なのが

    ctx = fjlib.page_context(request, site, tag, user, (sfeeds_obj, \
      sfeeds_ids))

なソレ。何を確認すれば良いのやら。とりあえずPython リファレンスマニュアルを見てみる。ええと、とりあえず 5.2.3 丸括弧形式 (parenthesized form) によれば上記の最後の引数は tuple ですな。メソド定義を見てみるに以下

def page_context(request, site, tag=None, user_id=None, sfeeds=None):

このメソドのドキュメント的には

Returns the context dictionary for a page view.

とある。あ、いきなり分けてますな。

    sfeeds_obj, sfeeds_ids = sfeeds

これって引数で別で頂くのと比べてどう効果があるんでしょ。とりあえず stack 消費が云々、とか引数少い方がナニ、とかなのかなぁ。しかし tuple をこうやってバラす事ができる、というのも凄い。
微妙なツッコミはさておき、次。

    try:
        page = int(request.GET.get('page', 0))
    except ValueError:
        page = 0

HTTP ヘッダに page ってナニが云々な処理。値が数値ではなかったら無理矢理 page の値を 0 にしているのが分かる。まぢで可読性高いな。次

    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

あ、しまった。object_list って何、と言いつつコードを見てみたら上記の if な命令の前に手続き呼び出しが御座いました。(職場メイルでこの書き方多い

    paginator, object_list = get_paginator(site, sfeeds_ids, \
      page=page, tag=tag, user=user_id)

get_paginator な手続きのナニが以下

def get_paginator(site, sfeeds_ids, page=0, tag=None, user=None):
    """ Returns a paginator object and a requested page from it.
    """

む。もしかして python ってデフォルトなソレ指定の引数は代入な式で書かないと駄目なのかなぁ。無駄な疑問はスルーとしてこれも順に見ていくと

    if tag:
        try:
            localposts = models.Tag.objects.get(name=tag).post_set.filter(\
              feed__in=sfeeds_ids)
        except:
            raise Http404
    else:
        localposts = models.Post.objects.filter(feed__in=sfeeds_ids)

    if user:
        try:
            localposts = localposts.filter(feed=user)
        except:
            raise Http404

なソレは tag と user で絞ってるのが分かる。user 指定だけでも何とかなる、という書き方になっていますな。絞る過程で not found な状態になった時点で 404 を戻す、というのもぱっと見分かる。
あら、でも

            localposts = models.Tag.objects.get(name=tag).post_set.filter(\
              feed__in=sfeeds_ids)

は微妙だなぁ。うーんと、データベース API リファレンスによれば

リレーションを張られた側からリレーションを張った側のモデルへのリンクも作成します

とある。Tag は Post 側で

    tags = models.ManyToManyField(Tag, verbose_name=_('tags'), filter_interface=models.VERTICAL)

なリレーションが設定されてて (Tag 側では皆無)、

models.Tag.objects.get(name=tag)

でタグなソレを取得した後に

post_set

で Post のレコードを上記のソレ (Tag) でシボって最後に filter してるのか。でも最後の filter の引数が微妙。上記のリファレンスによると in は指定されたリストの値と同じソレがあったら hit とゆー意味なはず。凄いですな。
がしかし次の user でシボる

            localposts = localposts.filter(feed=user)

ってのもアレだな。先のリファレンスの_逆方向_な部分によれば、

あるモデルが ForeignKey で別のモデルにリレーションを張っている場合、リレーションを張られた側のモデルのインスタンスは、リレーションを張った側のモデルの全てのインスタンスを返すマネジャにアクセスできるようになります

とある。ええと、Post は feed を ForeignKey にしてますな。引数 user って feed な id のリストじゃんか。引数の名前が微妙じゃないかと小一時間。でも文脈的にはこっちの方が良さげにも見えますな。

続々

別途余裕があれば続きを、とは言えそろそろ限界。