我已经包含了select_related
,总体上减少了查询和预取数据的数量。但是,我有一个单独查询的案例。我不确定我是否在期待一种不可能的行为。
我有以下看法:
list.py (查看)我在其中使用select_related
:
class OpportunitiesList(generics.ListAPIView):
serializer_class = OpportunityGetSerializer
def get_queryset(self):
queryset = Opportunity.objects.all()
queryset = queryset.filter(deleted=False)
return queryset.select_related('nearest_airport').order_by('id')
模型中有四个对象:opportunity.py(型号):
class Opportunity(models.Model):
deleted = models.BooleanField(
default=False,
)
opportunity_name = models.TextField(blank=True, null=True)
nearest_airport = models.ForeignKey(AirportDistance,
on_delete=models.SET_NULL,
db_column="nearest_airport",
null=True)
class AirportDistance(models.Model):
airport_id = models.ForeignKey(Airport,
on_delete=models.SET_NULL,
db_column="airport_id",
null=True)
airport_distance = models.DecimalField(max_digits=16, decimal_places=4, blank=False, null=False)
@property
def airport_name(self):
return self.airport_id.name
location_assets.py(Model):
class Location(models.Model):
name = models.CharField(null=True, blank=True, max_length=255)
location_fuzzy = models.BooleanField(
default=False,
help_text=
"This field should be set to True if the `point` field was not present in the original dataset "
"and is inferred or approximated by other fields.",
)
location_type = models.CharField(null=True, blank=True, max_length=255)
class Airport(Location):
description = models.CharField(null=True, blank=True, max_length=255)
aerodrome_status = models.CharField(null=True, blank=True, max_length=255)
aircraft_access_ind = models.CharField(null=True, blank=True, max_length=255)
data_source = models.CharField(null=True, blank=True, max_length=255)
data_source_year = models.CharField(null=True, blank=True, max_length=255)
class Meta:
ordering = ("id", )
最后,我有序列化器来转换数据:get.py:(序列化器)
class OpportunityGetSerializer(serializers.ModelSerializer):
nearest_airport = OpportunityAirportSerializer(required=False)
class Meta:
model = Opportunity
fields = (
"id",
"opportunity_name",
"nearest_airport",
)
distance.py (串行化程序)
class OpportunityAirportSerializer(serializers.ModelSerializer):
class Meta:
model = AirportDistance
fields = ('airport_id', 'airport_distance','airport_name')
上面创建了两个查询而不是一个:
SELECT opportunity.id,
opportunity.opportunity_name,
opportunity.nearest_airport,
airportdistance.id,
airportdistance.airport_id,
airportdistance.airport_distance
FROM opportunity
LEFT OUTER JOIN airportdistance
ON (opportunity.nearest_airport = airportdistance.id)
WHERE opportunity.deleted = false
ORDER BY opportunity.id ASC
SELECT location.name
FROM airport
INNER JOIN location
ON (airport.location_ptr_id = location.id)
WHERE airport.location_ptr_id = 1
AirportDistance
模型连接到Airport模型,Airport模型又连接到Location模型。在AirportDistance
中,我包含了一个混合属性,用于从Airport
中检索来自Location
模型的名称。我不确定这里的混合属性是否会影响select_related
。
可以只获取以下查询并混合两个查询:
SELECT opportunity.id,
opportunity.opportunity_name,
opportunity.nearest_airport,
airportdistance.id,
airportdistance.airport_id,
airportdistance.airport_distance,
location."name"
FROM opportunity
LEFT OUTER JOIN airportdistance
ON (opportunity.nearest_airport = airportdistance.id)
INNER join airport
ON (airport.location_ptr_id = airportdistance.airport_id)
INNER join location
ON (location.id = airport.location_ptr_id)
WHERE opportunity.deleted = false
ORDER BY opportunity.id ASC
1条答案
按热度按时间nzkunb0c1#
您需要执行
select_related('nearest_airport__airport_id')
而不是select_related('nearest_airport')
因为
AirportDistance
在解析airport_name
时访问airport_id.name
。