Imagine I have the next models (do not mind the field types, example purpose):
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()
and the corresponding serializations of these models
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')
Ok, so I'm using the Django REST Framework to build an API. One of the endpoints is /person
that returns all the persons.
def get(request):
persons = Person.objects.all()
data = PersonSerializer(persons, many = True)
return JsonResponse(data.data, safe = False)
The thing is: it takes so long to do the serialization of persons
because of the ForeignKey
s.
My main goal is to make the request go as fast as possible tweaking this code, models or serializers.
The easy [1] but, obviously not the best, is to store the actual strings of city
and country
inside the Person
model, and only serialize those, so the actual foreign keys are only used for querying and filtering purposes. But in that case, the scaling of that code is going to be awful(?).
I also tried using indexes but the improvement was not the one I was looking for.
Any suggestions or recommendations?
In my real case, I have a "Person
" model with 4 different foreign keys models (one of which has a foreign key model inside it) and the time difference between the natural way and the scrappy way [1] is ~7 s
vs ~1 ms
, respectively (what I consider a huge improvement).
Details:
- Approx. 1000 "persons" and 500 per "foreign keys" objects in my database.
- I also use a cache database, so the subsequent requests are not that bad (more or less a 25% of the initial), but the first one is awful...
Settings:
- Django:
1.11
- Python:
3.6