首页 > 解决方案 > 设计通知系统数据库的正确方法是什么?

问题描述

例如,我有以下模型

class User(models.Model):
    username = ...
    avatar = ...

class Article(models.Model):
    user = models.ForeignKey(User)
    title = ...
    content = ...

class Comment(models.Model):
    user = models.ForeignKey(User)
    # 'Comment' or 'Article'
    target_type = models.CharField()
    target_id = models.IntegerField()
    content = ...

class Like(models.Model):
    user = models.ForeignKey(User)
    # 'Comment' or 'Article'
    target_type = models.CharField()
    target_id = models.IntegerField()

Notification

class Notification(models.Model):
    actor = models.ForeignKey(User)
    receiver = models.ForeignKey(User)
    # 'Comment' or 'Like' or '@'
    verb = models.CharField()
    # Where the notification happens
    source_type = models.CharField()
    source_id = models.IntegerField()
    is_read = ...
    time = ...

source_type指示我需要查找哪个表并且source_idid那个表object(可能是 aComment或 aLike或其他)

我需要序列化notification如下:

[
{
    "actor": {
        "username": "Yriuns",
        "avatar": null
    },
    "verb": "Comment",
    "source": {
        "pk": 542,
        "user": {
            "username": "Yriuns",
            "avatar": null
        },
        "content": "this is a reply",
        "time": "2018.11.30 02:38",
        "target": {
            "pk": 540,
            "user": {
                "username": "Someone",
                "avatar": null
            },
            "content": "this is a comment"
        }
    },
    "time": "2018-11-30 02:38:08",
    "is_read": false
},
...
]

问题是:我不知道查询数据库(MySQL)获取source字段的有效方法。

例如,可能有 10 个通知,其中 5 个是Comment,其中 3 个是 ,其中Like2 个是@。到目前为止,我一一查询它们,这确实很慢。

注意 source有一个user字段,它也应该被查询。

  1. 我怎样才能加快速度?
  2. 我是否正确设计了数据库?

我试过GenericForeignKey了,它的效果不是很好,prefetch_related因为:

  1. 不同的型号有不同的ForeignKey,我只能prefetch_related说常见的。
  2. 我不能使用Prefetch()对象,因为GenericForeignKey不支持自定义查询集。

标签: pythondjangonotifications

解决方案


我认为Notification可以是您提供的这三个的基类(在django 模型实用user程序中具有公共属性). UsingInheritanceManager`,您可以在单个(不是那么优化,但仍然)查询中查询所有通知。

这些类型和 id 看起来也像一个通用的外键候选者。你看感谢解决方案吗?


推荐阅读