どういう問題が発生したの?¶
プライバシーポリシーの場所がタグ一覧とカテゴリ一覧の間に挟まって、見た目があんまりよろしくない。
デフォルトではPage
の順番はtitle
の名前順?になっているせいでこんなことになっている。
これを下の画像のようにしたい
どうやって解決したの?¶
まず、Pageの中でも順番を指定したいPageにおいて、変数order
を作成する。
Title: プライバシーポリシー
Order: -99
...
Title: 管理者情報
Order: -1
...
そして、theme
のbase.html
の以下の部分がPageのレイアウトを決めている部分。
{% if DISPLAY_PAGES_ON_MENU %}
{% for p in pages %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% else %}
これを以下のように変更した。
{% if DISPLAY_PAGES_ON_MENU %}
{% for p in pages | selectattr('order', 'undefined') %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% for p in pages | selectattr('order', 'defined') | sort(attribute='order') %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% else %}
これで、order
が定義されていないPage
は先頭でtitle
の順番で表示され、定義されているPage
はorder
の値に従って表示されるようになる。
詳しく説明¶
まず、設定したorder
等の変数はPage
に辞書みたいな感じで定義される。
pages
はPage
のリストである。
ここで|
の意味であるが、これはフィルターというらしく、まぁシェルのパイプラインと同義みたいなやつである。
pages
の一要素ごとにフィルターでselectattr
を用いてorder
が定義されているかを調べる。
定義されていないもの(undefined
)は最初のfor文で表示し、定義されているもの(defined
)は2つ目のfor文で表示する。
ここで、定義されている物では、そのorder
の値に従ってソートして、その大きさの順番に表示する。
一個一個追っていくと¶
page
は辞書だが、簡単のためにtitle
とorder
のタプルと考える。
そう考えると、最初は下のような順番になっている
[("カテゴリ一覧", None),
("プライバシーポリシー", -99),
("タグ一覧", None),
("管理者情報", -1)]
order
が定義されていないもの(None
になっているもの)をselectattr('order', 'undefined')
で取得すると、下のようなリストを得られる。
[("カテゴリ一覧", None),
("タグ一覧", None)]
次に、order
が定義されているものをselectattr('order', 'defined')
で取得すると、下のようなリストを得られる。
[("プライバシーポリシー", -99),
("管理者情報", -1)]
sort(attribute='order')
でソートすると、下のようなリストを得られる。
[("管理者情報", -1),
("プライバシーポリシー", -99)]
[("カテゴリ一覧", None),
("タグ一覧", None),
("管理者情報", -1),
("プライバシーポリシー", -99)]
まとめ¶
正直あんまり良いとは思えない実装だと感じるが、デフォルト値の設定ができなさそうなので、これで妥協した。
もしorder
のデフォルト値を設定できるなら、None
値を0
に設定したいところ。