django - 如何避免在 Django 中使用反向外键进行如此多的查询
问题描述
这些是我的模型(简化):
楷模:
class Tariff(models.Model):
name = models.CharField(max_length=25, blank=True, null=True)
service = models.ForeignKey(Service, models.DO_NOTHING, blank=True, null=True)
cost = models.DecimalField(max_digits=18, decimal_places=3, blank=True, null=True)
price = models.DecimalField(max_digits=18, decimal_places=3, blank=True, null=True)
datefrom = models.DateField(blank=True, null=True)
dateto = models.DateField(blank=True, null=True)
class Meta:
managed = True
db_table = 'Tariff'
class Service(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
city = models.ForeignKey(City, models.DO_NOTHING, blank=True, null=True)
class Meta:
managed = True
db_table = 'Service'
class CalendarValue(models.Model):
calendar = models.ForeignKey(Calendar, models.DO_NOTHING, blank=True, null=True)
service = models.ForeignKey(Service, models.DO_NOTHING, blank=True, null=True)
date = models.DateField(blank=True, null=True)
value = models.CharField(max_length=50, blank=True, null=True)
class Meta:
managed = True
db_table = 'CalendarValue'
序列化器:
class AvailabilitySerializer(serializers.ModelSerializer):
sum_cost = serializers.DecimalField(18, 3)
sum_price = serializers.DecimalField(18, 3)
service__id = serializers.IntegerField()
service__name = serializers.CharField()
calendarvalue = serializers.SerializerMethodField()
class Meta:
model = Tariff
fields = ('name', 'sum_cost', 'sum_price', 'service__id', 'service__name', 'calendarvalue')
def get_calendarvalue(self, tariff):
start_date = self.context.get('datefrom')
end_date = self.context.get('dateto')
service = Service.objects.get(id=tariff['service__id'])
return CalendarValueSerializer(CalendarValue.objects.filter(service=service,
date__range=[start_date, end_date]), read_only=True,
many=True).data
这很有效,我得到了所有关税,包括他们的服务和每项服务的所有日历值。
但我注意到它对每个服务进行查询以获取其日历值。
有没有办法在没有这么多查询的情况下获取所有数据?
谢谢。
我的观点
queryset = Tariff.objects.filter(datefrom__lte=start_date, dateto__gte=end_date)
queryset = queryset.filter(service__city=city_code)
# group by
queryset = queryset.values('name', 'service__id', 'service__name')\
.annotate(sum_cost=Sum('cost'), sum_price=Sum('price'), min_datefrom=Min('datefrom'), max_dateto=Max('dateto'))\
.order_by('service__id', 'name')
context = {'datefrom': start_date, 'dateto': end_date}
serializer = AvailabilitySerializer(queryset, many=True, context=context)
return serializer.data
我已阅读有关 prefetch_related 的信息,但我不知道如何实现它。
谢谢。
解决方案
推荐阅读
- spring-boot - 尝试从 docker 上发布的 Neo4jRepository 检索数据时出现 Neo4jSession 错误[ONLY DOCKER ISSUE]
- ios - 将 UIView/UIGestureRecognizer 添加到 UIPresentationController 中的呈现视图
- tensorflow - 如何在云中部署实时学习张量流模型?
- apache-spark - 提取键值时保持从 MapType 中键的顺序
- jenkins-pipeline - 从 shell 阶段中止 jenkins pipline 项目
- java - 登录后如何为不同角色的用户(如学生、教师和家长)添加导航抽屉?
- angular - 角度用 formArray 填充数据
- python - 寻求澄清 math.isclose()
- npm - npm install package global 并在一个 cmd 中链接
- c# - 删除一些带有特殊字符的特定字符串