POSTing большого количества связанных полей "многие ко многим" в django rest framework
Я создаю систему, подобную инвентаризации, используя Django Rest Framework, где у меня есть две модели (Category
и Location
), которые я хочу позволить User
добавить к своим Filter
, чтобы следить за ними.
#models.py
class Category (models.Model):
code=models.CharField(max_length=10, unique=True)
name=models.CharField(max_length=50)
class Location (models.Model):
code=models.CharField(max_length=10, unique=True)
name=models.CharField(max_length=50)
class Filter (models.Model):
categories = models.ManyToManyField(Category)
locations = models.ManyToManyField(Location)
name = models.CharField(max_length=50)
user = models.ForeignKey(User)
Я использую ModelSerializers и встроенные ModelViewSets.
#serializers.py
class UserFilterSerializer(serializers.ModelSerializer):
categories = serializers.SlugRelatedField(
queryset=Category.objects.all(), many=True, slug_field='code', allow_empty=False)
location = serializers.SlugRelatedField(
queryset=Location.objects.all(), many=True, slug_field='code', allow_empty=False)
user = serializers.HiddenField(
default=serializers.CreateOnlyDefault(default=serializers.CurrentUserDefault()))
class Meta:
model = UserTenderSelection
fields = ['id', 'categories', 'locations', 'name', 'user']
#views.py
class UserFilterView(ModelViewSet):
permission_classes = [IsAuthenticated]
serializer_class = UserFilterSerializer
pagination_class = None
def get_queryset(self):
return self.request.user.filter_set.prefetch_related("categories", "locations").all()
Я хочу, чтобы пользователи могли работать с фильтрами с помощью методов REST. Однако, вместо использования идентификаторов, мне нужно в какой-то момент использовать коды Category и Location как в GET ответах, так и в POST/PUT запросах. например,
//Example GET Response:
{
"id": 55,
"categories": [
"88-9",
"72-3",
],
"locations": [
"BE0",
"BE1",
"DE12"
],
"name": "Filter1"
}
//Example POST request:
{
"categories": [
"87-9",
"77-1",
],
"locations": [
"SP75",
"DE20"
],
"name": "Filter3"
}
Мой код отлично работает при малом количестве категорий и локаций, но при увеличении количества категорий и локаций он занимает слишком много времени. Например, POSTing фильтра с ~200 категориями и локациями в общей сложности занимает около 120 секунд, где 10 секунд уходит на запросы. Аналогично, когда я ПОЛУЧАЮ этот фильтр с ~200 элементами, он возвращается примерно за 20 секунд, где SQL занимает около 2 с. Запросы все еще высоки, однако это не является моей главной проблемой на данный момент. Я также пытался профилировать свой код, но я не смог пройти через толстый код django в CProfiler. У меня есть одна зацепка: в 10 секундах Query есть много обращений к уникальным кодам категорий, вероятно, из-за SlugRelatedField
с many=True
.
Возможно, я смогу обойтись пользовательским сериализатором и методами представления. Но поскольку это - вероятно - распространенный случай использования, я хочу найти решение, которое является лучшей практикой для DRF. Является ли SlugRelatedField неправильным выбором? Есть ли тип поля, который я могу использовать для этого случая?