[英]How to update queryset value in django?
I have written a python script in my project. 我在我的项目中编写了一个python脚本。 I want to update the value of a field. 我想更新字段的值。
Here are my modes 这是我的模式
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"]
This is my python script: 这是我的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()
After counting the total_rate from the Count table I want to update the total star value in News_Channel table. 从Count表中计算total_rate后,我想更新News_Channel表中的总星值。 I am failing to do so and get the data before the update and after the update as zero. 我没有这样做,并在更新之前和更新之后获取数据为零。 Although total_rate has value. 虽然total_rate有价值。
The reason why this fails is because here object
is a QuerySet
of News_Channel
s, yeah that QuerySet
might contain exactly one News_Channel
, but that is irrelevant. 为什么失败的原因是因为这里object
是一个QuerySet
的News_Channel
S,是啊是QuerySet
可能只包含一个News_Channel
,但是这是无关紧要的。
If you then use object[0]
you make a query to the database to fetch the first element and deserialize it into a News_Channel
object. 如果然后使用object[0]
,则向数据库进行查询以获取第一个元素并将其反序列化为News_Channel
对象。 Then you set the total_star
of that object, but you never save that object. 然后设置该对象的total_star
,但永远不保存该对象。 You only call .update()
on the entire queryset, resulting in another independent query. 您只在整个查询集上调用.update()
,从而产生另一个独立查询。
You can fix this with: 你可以解决这个问题:
objects = News_Channel.objects.filter(id=i)
object = objects[0]
object.total_star = total_rate
object.save()
Or given you do not need any validation, you can boost performance with: 或者,鉴于您不需要任何验证,您可以通过以下方式提高性能:
News_Channel.objects.filter(id=i).update(total_star=total_rate)
News_Channel
s 更新所有 News_Channel
If you want to update all News_Channel
s, you actually better use a Subquery
here: 如果要更新所有 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)
The reason is that object
in your case is a queryset, and after you attempt to update object[0]
, you don't store the results in the db, and don't refresh the queryset. 原因是您的情况下的object
是一个查询集,在您尝试更新object[0]
,您不会将结果存储在数据库中,也不会刷新查询集。 To get it to work you should pass the field you want to update into the update method. 要使其工作,您应该将要更新的字段传递给更新方法。
So, try this: 所以,试试这个:
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
can be calculated by using aggregation 可以使用聚合来计算News_Channel.total_star
news_channel_obj.count_set.aggregate(total_star=Sum('rate'))['total_star']
You can then either use this in your script: 然后,您可以在脚本中使用它:
object.total_star = object.count_set.aggregate(total_star=Sum('rate'))['total_star']
Or if you do not need to cache this value because performance is not an issue, you can remove the total_star field and add it as a property on the News_Channel
model 或者,如果您不需要缓存此值,因为性能不是问题,您可以删除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.