Message
模型:Post
模型相似,唯一的区别是有两个用户外键,一个用于发信人,另一个用于收信人。 User
模型可以获得这两个用户的关系,以及一个新字段,用于指示用户最后一次阅读他们的私有消息的时间:Message
一侧将添加author
和recipient
回调引用。 我之所以使用author
回调而不是更适合的sender
,是因为通过使用author
,我可以使用我用于用户动态的相同逻辑渲染这些消息。 last_message_read_time
字段将存储用户最后一次访问消息页面的时间,并将用于确定是否有比此字段更新时间戳的未读消息。 new_messages()
辅助方法实际上使用这个字段来返回用户有多少条未读消息。 在本章的最后,我将把这个数字作为页面顶部导航栏中的一个漂亮的徽章。User.last_message_read_time
字段。 这会将发送给该用户的所有消息标记为已读。 然后,我查询消息模型以获得消息列表,并按照最近的时间戳进行排序。我决定在这里复用POSTS_PER_PAGE
配置项,因为用户动态和消息的页面看起来非常相似,但是如果发生了分歧,为消息添加单独的配置变量也是有意义的。 分页逻辑与我用于用户动态的逻辑完全相同,因此这对你来说应该很熟悉。Message
具有额外的recipient
关系(我不需要在消息页面中显示,因为它总是当前用户),Post
和Message
实例具有几乎相同的结构。 所以我决定复用app/templates/_post.html子模板来渲染私有消息。 出于这个原因,这个模板使用了奇怪的for循环for post in messages
,以便私有消息的渲染也可以套用到子模板上。new_messages()
方法,并将该数字存储在new_messages
模板变量中。 然后,如果该变量不为零,我只需添加带有该数字的徽章到消息链接后面即可。 以下是这个页面的外观:new_messages
非零时,visibility
CSS属性设置为visible
;否则设置为hidden
。 我还为表示徽章的元素添加了一个id
属性,以便使用$('#message_count')
jQuery选择器来简化这个元素的选取。set_message_count()
函数将设置徽章元素中的消息数量,并调整可见性,以便在计数为0时隐藏徽章。set_message_count()
函数来使用户知道更新。time.time()
函数中获取。 每种类型的通知都会有所不同,所以我将它写为JSON字符串,因为这样可以编写列表,字典或单个值(如数字或字符串)。 为了方便,我添加了get_data()
方法,以便调用者不必操心JSON的反序列化。Message
和Notification
模型添加到shell上下文,这样我就可以直接在用flask shell
命令启动的解释器中使用这两个模型了。add_notification()
辅助方法,以便更轻松地处理这些对象:unread_message_count
。 如果数据库已经有一个带有这个名称的通知,例如值为3,则当用户收到新消息并且消息计数变为4时,我就会替换旧的通知。add_notification()
,以便我更新用户的通知,这样的地方有两处。 首先,在send_message()
视图函数中,当用户收到一个新的私有消息时:since
选项可以作为浮点数包含在请求URL的查询字符串中,其中包含开始时间的unix时间戳。 如果包含此参数,则只有在此时间之后发生的通知才会被返回。$(function() { ...})
模式。 这是注册一个函数在页面加载后执行的方式。 对于这个功能,我需要在页面加载时做的是设置一个定时器来获取用户的通知。 你还看到了setTimeout()
JavaScript函数,它在等待特定时间之后运行作为参数给出的函数。 setInterval()
函数使用与setTimeout()
相同的参数,但不是一次性触发定时器,而是定期调用回调函数。 本处,我的间隔设置为10秒(以毫秒为单位),所以我将以每分钟大约六次的频率查看通知是否有更新。unread_message_count
的通知时,通过调用上面定义的函数和通知中给出的计数来调整消息计数徽章。since
参数的方式可能会令人困惑。 我首先将这个参数初始化为0。 参数总是包含在请求URL中,但是我不能像以前那样使用Flask的url_for()
来生成查询字符串,因为一次请求中url_for()
只在服务器上运行一次,而我需要since
参数动态更新多次。 第一次,这个请求将被发送到 /notifications?since=0 ,但是一旦我收到通知,我就会将since
更新为它的时间戳。 这可以确保我不会收到重复的内容,因为我总是要求收到自我上次看到的通知以来发生的新通知。 同样重要的是要注意,我在interval函数外声明since
变量,因为我不希望它是局部变量,我想要在所有调用中使用相同的变量。