将slug化标题添加到网址
我有一个网址,比如 /posts/1
,这里的 1 是数据库中文章的编号。
@bp.route('/<post_id>')
@login_required
def post(post_id):
""" find the post and then show it """
p = Post.query.get(post_id)
return render_template("post/single_post.html", post=p)
不过,我想要的网址是带有某种简化标题的,比如 /posts/1/my_stack_overflow_question_is_bad
。我可以在模型里创建一个简化标题的属性:
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
html = db.Column(db.String)
@property
def slugified_title():
return slugify(self.title, separator="_", to_lower=True)
但是我该怎么把这个简化标题放进网址里呢?
1 个回答
8
你只需要在网址的路由中添加一个“slug”元素:
@bp.route('/<post_id>/<slug>')
@login_required
def post(post_id, slug):
""" find the post and then show it """
p = Post.query.get(post_id)
return render_template("post/single_post.html", post=p)
然后,当你想为它创建网址时,只需把这个“slug”放进 url_for
函数里:
p = Post.query.get(1)
url_for('post', post_id=p.id, slug=p.slugified_title)
不过这样做有点麻烦,所以我通常会使用一个叫做永久链接装饰器:
# Inspired by http://flask.pocoo.org/snippets/6/
from flask import url_for
def permalink(function):
def inner(*args, **kwargs):
endpoint, values = function(*args, **kwargs)
return url_for(endpoint, **values)
return inner
接着调整我的模型来使用这个装饰器:
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
html = db.Column(db.String)
@property
def slugified_title():
return slugify(self.title, separator="_", to_lower=True)
@permalink
def url(self):
# where 'post' is the title of your route that displays the post
return 'post', {'post_id': self.id, 'slug':self.slugified_title}
这样,当我需要一个网址时,我只需向对象请求它的网址,就不用手动经过 url_for
的步骤了。