不序列化外键字段以提高时间性能

时间:2019-06-04 15:41:12

标签: django serialization django-models django-rest-framework

想象一下我有下一个模型(不要介意字段类型,示例用途)

class County(model.Model):
   country = models.TextField()

class City(model.Model):
   country = models.ForeignKey(Country)
   city    = models.TextField()

class Person(model.Model):
   city = models.ForeignKey(City)
   name = models.TextField()

以及这些模型的相应序列化

class CountrySerializer(serializers.HyperlinkedModelSerializer):
   class Meta:
      model  = Country
      fields = ('country')

class CitySerializer(serializers.HyperlinkedModelSerializer):
   country = CountrySerializer()

   class Meta:
      model  = City
      fields = ('city', 'country')

class PersonSerializer(serializers.HyperlinkedModelSerializer):
   city = CitySerializer()

   class Meta:
      model  = Person
      fields = ('name', 'city')

好,所以我正在使用Django REST框架来构建API。端点之一是/person,它返回所有人员。

def get(request):
   persons = Person.objects.all()
   data = PersonSerializer(persons, many = True)
   return JsonResponse(data.data, safe = False) 

问题是:由于persons的原因,ForeignKey的序列化花费了很长时间。

我的主要目标是使请求尽可能快地调整此代码,模型或序列化器。

简单的[1],但显然不是最好的,是将citycountry的实际字符串存储在Person模型中,并且仅序列化它们,因此实际外键仅用于查询和过滤目的。但是在那种情况下,该代码的伸缩将是可怕的(?)。

我也尝试使用索引,但是改进并不是我想要的。

有什么建议或建议吗?

在我的真实情况下,我有一个“ Person”模型,其中包含4种不同的外键模型(其中一个内部具有外键模型),以及自然方式和草率方式之间的时差[ 1]分别为~7 s~1 ms(我认为这是巨大的改进)。

详细信息:

  • 约我的数据库中有1000个“ ”和每个“ 外键”对象500个。
  • 我还使用了一个缓存数据库,因此后续请求并没有那么糟糕(大约是初始请求的25%),但是第一个请求很糟糕...

设置:

  • Django:1.11
  • Python:3.6

1 个答案:

答案 0 :(得分:2)

相当相关的问题(哈哈)。通过这样的基本查找,您将拥有:

  • 1个数据库调用以获取所有Person对象(.all查找)

在序列化程序中,您将拥有:

  • 对于每个人,进行1次数据库调用以提取其city
    • 对于您获取的每个城市,添加1个数据库调用以获取该城市的country

您可以使用select_related来减少它:

Person.objects.select_related('city', 'city__country')

您还可以使用values查找来仅获取所需的字段,并在您的视图或SerializerMethodField中处理生成的平面字典。 How to combine select_related() and value()? (2016)