Flask中的slug字段
我想在数据库中创建一个“slug”字段。
我搜索了一下,找到了这个链接 http://flask.pocoo.org/snippets/5/,但是我在把代码整合到我的应用里时遇到了问题。
这是我的 modele.py
文件:
from unicodedata import normalize
def slugfy(text, encoding=None,
permitted_chars='abcdefghijklmnopqrstuvwxyz0123456789-'):
if isinstance(text, str):
text = text.decode(encoding or 'ascii')
clean_text = text.strip().replace(' ', '-').lower()
while '--' in clean_text:
clean_text = clean_text.replace('--', '-')
ascii_text = normalize('NFKD', clean_text).encode('ascii', 'ignore')
strict_text = map(lambda x: x if x in permitted_chars else '', ascii_text)
return ''.join(strict_text)
class Chanteur(db.Model):
id = db.Column(db.Integer, primary_key = True)
nom = db.Column(db.String(200), index = True, unique = True)
slug = db.Column(db.String(255))
chanteurs = db.relationship('Chanson', backref = 'chanteur', lazy = 'dynamic')
def __repr__(self):
return '<Chanteur %r>' % (self.nom)
def __setattr__(self, key, value):
super(Chanteur, self).__setattr__(key, value)
if key == 'nom':
self.slug = slugfy(self.nom)
class Chanson(db.Model):
id = db.Column(db.Integer, primary_key = True)
titre = db.Column(db.String(255))
chanteur_id = db.Column(db.Integer, db.ForeignKey('chanteur.id'))
def __repr__(self):
return '<Chanson %r>' % (self.titre)
它没有正常工作:当我添加一个新的对象(比如歌手)时,slug 字段是空的。
6 个回答
0
我写了一篇关于这个话题的文章。我的方法是使用会话的 'before_commit' 事件。你可以在 这里 阅读更多内容。
0
你好,
如果你想让“slug”字段代表歌曲的标题,可以这样做。
from unicodedata import normalize
def slug(text, encoding=None,
permitted_chars='abcdefghijklmnopqrstuvwxyz0123456789-'):
if isinstance(text, str):
text = text.decode(encoding or 'ascii')
clean_text = text.strip().replace(' ', '-').lower()
while '--' in clean_text:
clean_text = clean_text.replace('--', '-')
ascii_text = normalize('NFKD', clean_text).encode('ascii', 'ignore')
strict_text = map(lambda x: x if x in permitted_chars else '', ascii_text)
return ''.join(strict_text)
class Chanson(object):
titre = ''
slugfield = ''
def __setattr__(self, key, value):
super(Chanson, self).__setattr__(key, value)
if key == 'titre':
self.slugfield = slug(self.titre)
m = Chanson()
m.titre = 'Non, je ne regrette rien'
print m.titre
print m.slugfield
这个“slug”方法是从这里获取的。
编辑过
def slug(text):
#slugfy logic here
class Chanson(db.Model):
id = db.Column(db.Integer, primary_key = True)
titre = db.Column(db.String(255))
chanteur_id = db.Column(db.Integer, db.ForeignKey('chanteur.id'))
slugfield = db.Column(db.String(255))
def __setattr__(self, key, value):
super(Chanson, self).__setattr__(key, value)
if key == 'titre':
self.slugfield = slug(self.titre)
1
安装一个叫做 Webhelpers 的软件包,它可以让你轻松搞定“slug化”这个过程。
from webhelpers.text import urlify
class Chanteur(db.Model):
id = db.Column(db.Integer, primary_key=True)
nom = db.Column(db.String(200), index=True, unique=True)
chanteurs = db.relationship('Chanson', backref='chanteur', lazy='dynamic')
def __repr__(self):
return '<Chanteur %r>' % (self.nom)
@property
def slug(self):
return urlify(self.nom)
class Chanson(db.Model):
id = db.Column(db.Integer, primary_key=True)
titre = db.Column(db.String(255))
chanteur_id = db.Column(db.Integer, db.ForeignKey('chanteur.id'))
def __repr__(self):
return '<Chanson %r>' % (self.titre)
@property
def slug(self):
return urlify(self.nom)
想了解更多信息,可以参考 文档。
8
这是对@berislav-lopac建议的小改进。使用python-slugify,你可以这样做:
from slugify import slugify
class SlugModel(Base):
name = Column(String)
slug = Column(String)
@staticmethod
def slugify(target, value, oldvalue, initiator):
if value and (not target.slug or value != oldvalue):
target.slug = slugify(value)
event.listen(SlugModel.name, 'set', SlugModel.slugify, retval=False)
这样在创建或更新时,会自动更新slug的内容。
如果你想要更好的解决方案,可以使用@hybrid_property这个装饰器,具体建议可以参考这里。
18
为了把这个“slug”(通常是指网址中用来表示某个内容的简短、易读的字符串)保存到数据库里,我采用了以下的方法(使用了一个非常有用的python-slugify
库):
from slugify import slugify # among other things
class Song(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(255))
slug = db.Column(db.String(255))
def __init__(self, *args, **kwargs):
if not 'slug' in kwargs:
kwargs['slug'] = slugify(kwargs.get('title', ''))
super().__init__(*args, **kwargs)