備忘録です。
今回の備忘録は記事を投稿するときに同時にタグを設定できるようにし、そのタグで記事をソートして表示する方法です。

タグ
同じタグがついている記事を集めて表示する
hatenaブログでもありますが、記事を投稿するときにタグをつけておけば、後でタグで記事を選別できます。同じ機能をFlaskのアプリに設置します。(今回、設置できるタグは1記事につき1つです)
その1 記事のテーブルにタグを設置
class Knowledge(db.Model):
id = db.Column(db.Integer, primary_key=True)
k_title = db.Column(db.String(255))
k_content = db.Column(db.Text)
k_tag = db.Column(db.String(100))
k_created_at = db.Column(db.DateTime, default=datetime.now(pytz.timezone('Asia/Tokyo')))そ
そのまま、String型でカラムを作ります。
その2 記事一覧ページの上部にタグを表示する

タイトルの下にある2つのボタン(Flask、記事)が記事投稿時にタグとして登録したものを表示したものです。ボタンになっているので、こちらをクリックするとそのタグのページに飛ぶようにします。
一覧ページ用のコードは下記のようにしました。
#app.py
@app.route('/knowledges')
def knowledges():
knowledges = Knowledge.query.order_by(desc(Knowledge.k_created_at))
tags = list(set([knowledge.k_tag for knowledge in knowledges]))
return render_template('knowledges.html', knowledges=knowledges, tags=tags)
returnする前にtagsという変数にタグ(k_tag)としてDBに登録されているデータを集めて格納しています。
この時、タグの重複を削除するために一度、タグのリストをset()して再度list()しています。
htmlは下記のようにしました。
# knowledges.html
{% extends "base.html"%}
{% block content %}
<a href="{{url_for('add_knowledge')}}" class="btn btn-outline-primary float-end mt-2">ナレッジ登録</a>
<h1 class="mt-4">ナレッジ一覧</h1><br/>
# app.pyの関数で渡されたリストtagsをここで拾っています。forで取り出しボタンにして表示します。
{% for tag in tags %}
# url_forでtag=tagでクリックしたtagを渡します
<a href="{{ url_for('search_tag', tag=tag)}}" class="btn btn-outline-secondary btn-sm mb-2">{{ tag }}</a>
{% endfor %}
{% for knowledge in knowledges %}
<div class="shadow p-3 mb-5 bg-body rounded">
<h2>{{ knowledge.k_title }}</h2>
<small>作成日:{{ knowledge.k_created_at.strftime('%Y-%m-%d %H:%M') }}</small><br/>
{{ knowledge.k_content }} <br/><br/>
{{ knowledge.k_tag}} <br/><br/>
<a href="{{ url_for('edit_knowledge', id=knowledge.id) }}" class="btn btn-outline-secondary btn-sm">編集</a>
<a href="{{ url_for('delete_knowledge', id=knowledge.id) }}" class="btn btn-outline-danger btn-sm">削除</a>
</div>
{% endfor %}
{% endblock %}
その3 ボタンを押してタグのページに遷移させる
選択したタグのページを作ります。
@app.route('/knowledges/tags/<tag>')
def search_tag(tag):
knowledges = Knowledge.query.filter(Knowledge.k_tag == tag).order_by(desc(Knowledge.k_created_at))
return render_template('tags.html', knowledges=knowledges, tag=tag)
routeにtagを渡しています。これは一覧ページのボタンから渡されているタグです。
関数内でそのtagをもとにDBにfilterをかけて取り出し、念の為order_by()のdesc()で降順に並べ替え変数に格納しています。
returnでtagをさらに渡しているのは、表示するページでそのtagを使いたいからです。
{% extends "base.html"%}
{% block content %}
<a href="{{url_for('add_knowledge')}}" class="btn btn-outline-primary float-end mt-2">ナレッジ登録</a>
<h1 class="mt-4">{{tag}}</h1><br/>
{% for knowledge in knowledges %}
<div class="shadow p-3 mb-5 bg-body rounded">
<h2>{{ knowledge.k_title }}</h2>
<small>作成日:{{ knowledge.k_created_at.strftime('%Y-%m-%d %H:%M') }}</small><br/>
{{ knowledge.k_content }} <br/><br/>
{{ knowledge.k_tag}} <br/><br/>
<a href="{{ url_for('edit_knowledge', id=knowledge.id) }}" class="btn btn-outline-secondary btn-sm">編集</a>
<a href="{{ url_for('delete_knowledge', id=knowledge.id) }}" class="btn btn-outline-danger btn-sm">削除</a>
</div>
{% endfor %}
{% endblock %}
今回は、ページ遷移させました。同じページで表示内容を変えることも考えたのですが、こっちの方が単純そうなのでこっちにしました。

「記事」というタグに紐づく記事を表示したページはこうなります。