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 неправильным выбором? Есть ли тип поля, который я могу использовать для этого случая?

Вернуться на верх