Django select_related 不按预期工作

问题描述

我有 2 个类,国家和坐标。在对 Country 表进行 API 调用时,我希望 API(使用 DRF)也返回相关的坐标信息。

认情况下,可以理解地返回以下内容 (localhost:8000/api/country/):

{
    "id": 1,"name": "TestCountry","coordinates": 1
}

问题是在我的 views.py 文件中实现 select_related 并修改 CountrySerializer 后,输出保持完全相同。我曾期待这样的事情:

{
    "id": 1,"coordinates": {
        "longitude": 123,"latitude": 456,}
}

或者即使这样就足够了:

{
    "id": 1,"longitude": 123,}

这里是模型、视图和序列化文件中的相关代码

class Coordinates(models.Model):
    longitude = models.DecimalField()
    latitude = models.DecimalField()

class Country(models.Model):
    name = models.CharField()
    coordinatesID = models.ForeignKey(Coordinates,on_delete=models.SET_NULL,verbose_name="Coordinates",db_column="CoordinatesID",blank=True,null=True,related_name="coordinates")

class CountryViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Country.objects.select_related('coordinatesID').all()
    serializer_class = CountrySerializer

class CountrySerializer(DynamicFieldModelSerializer):
    longitude = serializers.ReadOnlyField(source='coordinates.longitude')
    latitude = serializers.ReadOnlyField(source='coordinates.latitude')

    class Meta:
        model = Country
        fields = '__all__'

另外,在 Country 表中,我指定了 related_name="coordinates",但是 select_related 不识别此选项,我仍然必须使用 “coordinatesID” 引用坐标表。这是错误还是与不正确的实施有关?

解决方法

请注意,related_name 用于从 Coordinates 模型端到 Country 端反向访问关系,而不是相反。

因此在 select_related 中您可以使用在模型本身上定义的所有字段和关系,因此对于 Country 模型,如果您将坐标关系定义为 coordinatesID,您将需要执行像这样

queryset = Country.objects.select_related('coordinatesID').all()

并在序列化程序中使用

longitude = serializers.ReadOnlyField(source='coordinatesID.longitude')
latitude = serializers.ReadOnlyField(source='coordinatesID.latitude')

还使用像 coordinatesID 这样的字段名称在 Django 中并不是很好的命名约定,因为你会有一个像 coordinatesID.id 这样的属性,它不是很干净。

https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/