假设我有这个模型(不是真正的代码):
class Message(models.Model):
content = models.CharField(...)
mentions = models.ManyToManyField(User)
内容可以是:
Say hi to @Adam and @Bernard
在消息模型 save() 期间,从文本中提取“Adam”和“Bernard”,并将其各自的用户实例添加到提及中,以便
>>> m = Message.objects.create(content="Say hi to @Adam and @Bernard")
>>> m.mentions.all()
>>> [User: Adam, User: Bernard]
现在,关于我的问题:
我该如何应对伯纳德进行变性并将自己改名为伯纳德?我非常希望接下来阅读向@Adam 和@Bernarda 打个招呼
。
基本上,我尝试了一种在保存时用ID替换名称的策略(向@Adam和@Bernard打招呼
然后变成向@1和@2打招呼
,即他们的 User.pk 的)。保存时效果很好,读取时效果还不错。
在模型的 save() 方法中进行此替换工作正常,但读取和查找操作是一个主要问题。我找不到一种简单的方法来确保数据库中存储的内容(即向@1和@2问好
)“神奇地”变成向@Adam和@Bernard问好
每当它被查询(通过 .filter() 和相关操作)或其实例被评估时。
我不确定我是否走在正确的道路上;非常欢迎任何以不同方式进行此操作的指示或想法!
最佳答案
编写一个扩展 CharField 的自定义模型字段类,您应该重写 the documentation first这样你就知道那里有什么,
自定义 Field 需要 metaclass = models.SubfieldBase 来调用自定义 to_python 方法
重写 to_python(), it takes a database value并且应该返回一个Python值,在那里你可以用用户#1的用户名替换@1(比如@Adam或@Bernarda),
重写 get_prep_value(), it takes a python value并应返回 SQL 的值,您可以将 @Adam 替换为用户管理员的 pk(例如 @1),
查询提及,例如
Message.objects.filter(mention=someuser)
,或创建另一个字段:一个包含替换版本,一个包含替换版本其中包含可能已过时的用户名 - 我不推荐后者您还可以查询内容,例如
Message.objects.filter(content__contains='@1')
Voodoo 一般来说没有任何好处,我会创建一个模型方法 get_content_display()
来进行替换,以及一个显示 html 版本的 templatetag内容 - 因为你可能想将 @Adam 链接到他的用户页面。我会坚持这个,因为那是 KISS .
感谢 LaundroMat 调试此答案并修复它(有 2 个错误和 1 个不准确之处,他调试并回来报告!!!)。另外支持他的评论,除非你有更好的方法来奖励他。摇滚起来。
关于python - 保存和读取数据库时转换数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8678047/