どういう問題が発生したの?¶
プライバシーポリシーの場所がタグ一覧とカテゴリ一覧の間に挟まって、見た目があんまりよろしくない。
デフォルトでは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に設定したいところ。