如何更新 Django 中的查询集值?

ims*_*ful 4 python django django-models django-queryset

我在我的项目中编写了一个 python 脚本。我想更新一个字段的值。

这是我的模式


class News_Channel(models.Model):
    name = models.TextField(blank=False)
    info = models.TextField(blank=False)
    image = models.FileField()
    website = models.TextField()
    total_star = models.PositiveIntegerField(default=0)
    total_user = models.IntegerField()

    class Meta:
        ordering = ["-id"]

    def __str__(self):
        return self.name

class Count(models.Model):
    userId = models.ForeignKey(User, on_delete=models.CASCADE)
    channelId = models.ForeignKey(News_Channel, on_delete=models.CASCADE)
    rate = models.PositiveIntegerField(default=0)

    def __str__(self):
        return self.channelId.name

    class Meta:
        ordering = ["-id"]
Run Code Online (Sandbox Code Playgroud)

这是我的python脚本:

from feed.models import Count, News_Channel


def run():
    for i in range(1, 11):
        news_channel = Count.objects.filter(channelId=i)
        total_rate = 0
        for rate in news_channel:
            total_rate += rate.rate
        print(total_rate)
        object = News_Channel.objects.filter(id=i)
        print(total_rate)
        print("before",object[0].total_star,total_rate)
        object[0].total_star = total_rate
        print("after", object[0].total_star)
        object.update()

Run Code Online (Sandbox Code Playgroud)

从 Count 表计算 total_rate 后,我想更新 News_Channel 表中的总星级值。我没有这样做并且将更新之前和更新之后的数据设为零。尽管 total_rate 有价值。

Wil*_*sem 6

问题

这失败的原因是因为这里object是 a QuerySetof News_Channels,是的,QuerySet可能只包含一个News_Channel,但这无关紧要。

如果随后使用object[0],则对数据库进行查询以获取第一个元素并将其反序列化为News_Channel对象。然后您设置该total_star对象的 ,但您永远不会保存该对象。您只需拨打.update()整个查询集,导致另一个独立的查询。

您可以通过以下方式解决此问题:

objects = News_Channel.objects.filter(id=i)
object = objects[0]
object.total_star = total_rate
object.save()
Run Code Online (Sandbox Code Playgroud)

或者假设您不需要任何验证,您可以通过以下方式提高性能:

News_Channel.objects.filter(id=i).update(total_star=total_rate)
Run Code Online (Sandbox Code Playgroud)

更新所有 News_Channels

如果要更新所有 News_Channels,实际上最好在Subquery此处使用 a :

from django.db.models import OuterRef, Sum, Subquery

subq = Subquery(
    Count.objects.filter(
        channelId=OuterRef('id')
    ).annotate(
        total_rate=Sum('rate')
    ).order_by('channelId').values('total_rate')[:1]
)

News_Channel.objects.update(total_star=subq)
Run Code Online (Sandbox Code Playgroud)


NS0*_*NS0 5

原因是object在您的情况下是一个查询集,并且在您尝试更新之后object[0],您不会将结果存储在数据库中,也不会刷新查询集。要使其工作,您应该将要更新的字段传递到 update 方法中。

所以,试试这个:

def run():
    for i in range(1, 11):
        news_channel = Count.objects.filter(channelId=i)
        total_rate = 0
        for rate in news_channel:
            total_rate += rate.rate
        print(total_rate)
        object = News_Channel.objects.filter(id=i)
        print(total_rate)
        print("before",object[0].total_star,total_rate)
        object.update(total_star=total_rate)
        print("after", object[0].total_star)
Run Code Online (Sandbox Code Playgroud)