Skip to main content
 首页 » 编程设计

python之如何使用 Django ORM 获得额外的计数字段

2024年08月25日29zdz8207

我的 Django 模型是这样的:

class User(models.Model): 
    username = models.CharField(max_length=32) 
class Message(models.Model): 
    content = models.TextField() 
class UserMessageRel(models.Model): 
    user = models.ForeignKey(User) 
    message = models.ForeignKey(Message) 
    is_read = models.BooleanField() 

现在我想获取所有消息,对于每条消息,我需要知道有多少用户阅读了它。

最简单的做法是:

msgs = Message.objects.all() 
messages = [] 
for msg in msgs: 
    reads = UserMessageRel.objects.filter(message=msg, is_read=True).count() 
    messages.append((msg, reads)) 

但是这样效率很低,用SQL查询获取每条消息的阅读次数。

我不确定这是否可以通过 ORM 中的注释或聚合来完成?

我想要的是这样的:

msgs_with_reads = Message.objects.all().annotate( 
    number_of_reads=Count("user_message_rel_with_is_read_true")) 

可以转换成一个很好的 SQL 查询。

这是可以实现的吗?

请您参考如下方法:

我将您的问题解释为您想缩短此计数的查询时间。不幸的是,在当前设置下,需要进行全表扫描。有很多方法可以改进它,最简单的是索引。您可以在 UserMessageRel 中的 Message id 列上添加一个索引,这将加快读取时间(当然是以空间为代价)。不过,访问此计数的最可读方式是 Pieter 的回答。