簡體   English   中英

如何在django中更新queryset值?

[英]How to update queryset value in django?

我在我的項目中編寫了一個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"]

這是我的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()

從Count表中計算total_rate后,我想更新News_Channel表中的總星值。 我沒有這樣做,並在更新之前和更新之后獲取數據為零。 雖然total_rate有價值。

問題

為什么失敗的原因是因為這里object是一個QuerySetNews_Channel S,是啊是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()

或者,鑒於您不需要任何驗證,您可以通過以下方式提高性能:

News_Channel.objects.filter(id=i).update(total_star=total_rate)

更新所有 News_Channel

如果要更新所有 News_Channel ,實際上最好使用Subquery

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)

原因是您的情況下的object是一個查詢集,在您嘗試更新object[0] ,您不會將結果存儲在數據庫中,也不會刷新查詢集。 要使其工作,您應該將要更新的字段傳遞給更新方法。

所以,試試這個:

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)

可以使用聚合來計算News_Channel.total_star

news_channel_obj.count_set.aggregate(total_star=Sum('rate'))['total_star']

然后,您可以在腳本中使用它:

object.total_star = object.count_set.aggregate(total_star=Sum('rate'))['total_star']

或者,如果您不需要緩存此值,因為性能不是問題,您可以刪除total_star字段並將其添加為News_Channel模型上的屬性

@property
def total_star(self):
    return self.count_set.aggregate(total_star=Sum('rate'))['total_star']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM