所以我叫我的序列化器是这样的:
result_serializer = TaskInfoSerializer(tasks, many=True)
和序列化器:
class TaskInfoSerializer(serializers.ModelSerializer):
done_jobs_count = serializers.SerializerMethodField()
total_jobs_count = serializers.SerializerMethodField()
task_status = serializers.SerializerMethodField()
class Meta:
model = Task
fields = ('task_id', 'task_name', 'done_jobs_count', 'total_jobs_count', 'task_status')
def get_done_jobs_count(self, obj):
qs = Job.objects.filter(task__task_id=obj.task_id, done_flag=1)
condition = False
# Some complicate logic to determine condition that I can't reveal due to business
result = qs.count() if condition else 0
# this function take around 3 seconds
return result
def get_total_jobs_count(self, obj):
qs = Job.objects.filter(task__task_id=obj.task_id)
# this query take around 3-5 seconds
return qs.count()
def get_task_status(self, obj):
done_count = self.get_done_jobs_count(obj)
total_count = self.get_total_jobs_count(obj)
if done_count >= total_count:
return 'done'
else:
return 'not yet'
当调用get_task_status函数时,它将调用其他2个函数,并再次进行这2个代价高昂的查询。 有什么最好的方法来防止这种情况吗?而且我真的不知道这些函数的调用顺序,它是基于Meta字段中声明的顺序吗?还是在那之上?
编辑: get_done_jobs_count中的逻辑有点复杂,在获取任务时,我无法使其成为单个查询
修改2: 我只是将所有这些count函数带入模型并使用cached_property https://docs.djangoproject.com/en/2.1/ref/utils/#module-django.utils.functional 但这又提出了一个问题:这个数字可靠吗?我对django缓存了解不多,是cached_property仅存在于此实例(直到API get任务列表返回响应)还是存在一段时间?
答案 0 :(得分:1)
我只是尝试使用cached_property,它确实解决了问题。
型号:
from django.utils.functional import cached_property
from django.db import models
class Task(models.Model):
task_id = models.AutoField(primary_key=True)
task_name = models.CharField(default='')
@cached_property
def done_jobs_count(self):
qs = self.jobs.filter(done_flag=1)
condition = False
# Some complicate logic to determine condition that I can't reveal due to business
result = qs.count() if condition else 0
# this function take around 3 seconds
return result
@cached_property
def total_jobs_count(self):
qs = Job.objects.filter(task__task_id=obj.task_id)
# this query take around 3-5 seconds
return qs.count()
@property
def task_status(self):
done_count = self.done_jobs_count
total_count = self.total_jobs_count
if done_count >= total_count:
return 'done'
else:
return 'not yet'
序列化器:
class TaskInfoSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ('task_id', 'task_name', 'done_jobs_count', 'total_jobs_count', 'task_status')
答案 1 :(得分:0)
您可以注释这些值,以避免进行额外的查询。因此,传递给序列化程序的queryset看起来像这样(它可能会根据您使用的Django版本和作业的相关查询名称而变化):
#include <iostream>
using namespace std;
int main()
{
float x, z, a;
a = x + z;
cout << "Welcome to the calculator" << endl;
cout << "State the first number " << endl;
cin >> x ;
cout << "State the second number " << endl;
cin >> z ;
cout << "If you wanted to time number" << x << "by this number" << z << "The result would be : " << a << endl;
system("pause");
return 0;
}
然后序列化器方法如下:
tasks = tasks.annotate(
done_jobs=Count('jobs', filter=Q(done_flag=1)),
total_jobs=Count('jobs'),
)
result_serializer = TaskInfoSerializer(tasks, many=True)
编辑:如果必须为每个任务实例调用该方法,那么cached_property将无济于事(似乎是这种情况)。问题不在于计算,而在于您是否必须为每个单独的任务访问数据库。您必须集中精力在单个查询中获得计算所需的所有信息。如果那不可能或太复杂,也许可以考虑更改数据结构(模型)以便于实现。
答案 2 :(得分:-1)
使用 iterator()并计算Iterator可能会解决您的问题。
job_iter = Job.objects.filter(task__task_id=obj.task_id).iterator()
count = len(list(job_iter))
return count
如果需要,可以使用select_related()和prefetch_related()一次检索所有内容。
注意 :如果使用 iterator()运行查询,则 prefetch_related()通话将被忽略
您可能想浏览optimisation的文档