我在MongoDB中有文章。我希望文章的URL可读。如果我有一篇名为"如何与Heroku"无缝使用Flask和MongoDB的文章,我希望网址类似于localhost:5000/blog/how-to-use-flask-and-mongodb-seamlessly-with-heroku
。
实现这一目标的最佳方法是什么?任何指向正确方向的人都会受到赞赏。我不确定从哪一个开始。
答案 0 :(得分:6)
您正在寻找一种方法来生成" slug"并用它来识别帖子。
如果你只想使用一个slug,所有帖子都必须有一个独特的slug(大约意味着一个独特的标题)。这也意味着如果您更改帖子的标题,则网址可能会更改,这会使书签和其他外部链接无效。
更好的方法是执行Stack Overflow针对问题所做的事情。如果您查看此问题的网址,您会注意到它有一个唯一的ID和一个slug。实际上,slug是可选的,您仍然可以通过从URL中删除它来访问此页面。
您需要一种方法来生成slug和自定义url converter。 inflection库提供了一种使用parameterize
方法强化字符串的好方法。以下url转换器获取一个对象,并返回一个包含the_object.id
和the_object.title
作为slug的url。在解析网址时,它只返回对象的id
,因为slug是可选的。
from inflection import parameterize
from werkzeug.routing import BaseConverter
class IDSlugConverter(BaseConverter):
"""Matches an int id and optional slug, separated by "/".
:param attr: name of field to slugify, or None for default of str(instance)
:param length: max length of slug when building url
"""
regex = r'-?\d+(?:/[\w\-]*)?'
def __init__(self, map, attr='title', length=80):
self.attr = attr
self.length = int(length)
super(IDSlugConverter, self).__init__(map)
def to_python(self, value):
id, slug = (value.split('/') + [None])[:2]
return int(id)
def to_url(self, value):
raw = str(value) if self.attr is None else getattr(value, self.attr, '')
slug = parameterize(raw)[:self.length].rstrip('-')
return '{}/{}'.format(value.id, slug).rstrip('/')
注册转换器,以便在路线中使用:
app.url_map.converters['id_slug'] = IDSlugConverter
在路线中使用它:
@app.route('/blog/<id_slug:id>')
def blog_post(id):
# get post by id, do stuff
为帖子生成网址。请注意,您将对象(&#39; post&#39;)而不仅仅是id传递给id参数。:
url_for('blog_post', id=post)
# /blog/1234/the-post-title
我为Stack Overflow Python聊天室site编写的转换器。