Я вижу, и для этого ответ использования необработанного SQL может быть правильным (я, конечно, не пытался обмануть этот ответ!). Но я думаю, что рассматриваемый код может не соответствовать тому, как лучше настроить вашу API-архитектуру с точки зрения производительности, поэтому я предложил пересмотреть вывод, а не пытаться его создать.

авляю поле «добавлено», чтобы проверить, к каким категориям добавляется пост пользователя (экипировка). Звучит ужасно, поэтому давайте углубимся в код.

Я хочу оптимизировать функцию get_categories (self, obj).

class CategorySerializer(serializers.ModelSerializer):
    added = serializers.BooleanField()
    class Meta:
        model = Category
        fields = (
            'id',
            'name',
            'added'
        )


class OutfitDetailSerializer(serializers.ModelSerializer):

    def get_categories(self, obj):
        user = self.context['request'].user
        categories = Category.objects.filter(owner=user)
        added = categories.extra(select={'added': '1'}).filter(outfits__pk=obj.pk)
        added = list(added.values('added', 'name', 'id'))
        added_f = categories.extra(select={'added': '0'}).exclude(outfits__pk=obj.pk)
        added_f = list(added_f.values('added', 'name', 'id'))
        categories = added + added_f
        return CategorySerializer(categories, many=True).data

Выход ниже!

"categories": [{
        "id": 1,
        "name": "Gym",
        "added": true
    }, {
        "id": 2,
        "name": "School",
        "added": false
    }, {
        "id": 3,
        "name": "hollymo",
        "added": true
    }, {
        "id": 4,
        "name": "Normal",
        "added": false
    }, {
        "id": 6,
        "name": "New Category",
        "added": false
    }
]

Вот models.py

class Outfit(models.Model):
    ...
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    content = models.CharField(max_length=30)
    ...

class Category(models.Model):
    name = models.CharField(max_length=20)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    outfits = models.ManyToManyField(Outfit, related_name="categories", blank=True)
    main_img = models.ImageField(
                            upload_to=upload_location_category,
                            null=True,
                            blank=True)
    ...

здесьрепо для теста

 Bear Brown21 сент. 2017 г., 11:58
будет лучше добавить ваши модели к текущему вопросу, более понятным для других людей
 John Baek21 сент. 2017 г., 11:59
хорошо всего на секунду

Ответы на вопрос(2)

вы просто хотите «проверить, к каким категориям добавляется пост пользователя (экипировка)». Для этого вам нужно будет только вернуть те, которые добавлены = верно, верно? и тогда вы можете оставить добавленный ключ.

как в:

"categories": [{
        "id": 1,
        "name": "Gym"
    }, {
        "id": 3,
        "name": "hollymo"
    }
]

Если это так, вы можете просто использовать:

import Category from category.models

class CategoriesSerializer(serializers.ModelSerializer):

    class Meta:
        model = Category
        fields = ('id', 'name')

class OutfitDetailSerializer(serializers.ModelSerializer):
    categories = CategoriesSerializer(many=True)

Если вместо этого ваш вариант использования состоит в том, чтобы показать список всех категорий, а затем сделать что-то только с теми, к которым добавлен текущий наряд, я бы предложил сделать 2 вызова API вместо вашей текущей логики; Один с ответом, который я поставил выше, и один, чтобы получить все категории. Затем сделайте эту «добавленную» логику в вашем внешнем интерфейсе как логику его уровня представления.

Я бы, конечно, старался избегать выполнения необработанных SQL-запросов в Django, это сокращает цель миграции и редко требуется.

 Bear Brown22 сент. 2017 г., 16:54
код в вопросе работает правильно, но в настоящее время OP хочет знать, есть ли способ минимизировать запрос к базе данных.
 Vincent22 сент. 2017 г., 17:47
Я вижу, и для этого ответ использования необработанного SQL может быть правильным (я, конечно, не пытался обмануть этот ответ!). Но я думаю, что рассматриваемый код может не соответствовать тому, как лучше настроить вашу API-архитектуру с точки зрения производительности, поэтому я предложил пересмотреть вывод, а не пытаться его создать.
Решение Вопроса

вы можете получить необходимые данные сdjango raw sql:

q = """\
SELECT yourappname_category.id,
       yourappname_category.name,
       COUNT(outfit_id) > 0 as added 
FROM yourappname_category
  LEFT JOIN yourappname_category_outfits 
      ON yourappname_category.id = yourappname_category_outfits.category_id 
         AND yourappname_category_outfits.outfit_id=%s
WHERE yourappname_category.owner_id=%s
GROUP BY yourappname_category.id, yourappname_category.name"""

categories = Category.objects.raw(q, [obj.id, user.id])
results = [{'id': c.id, 'name': c.name, 'added': c.added} for c in categories]
 John Baek22 сент. 2017 г., 04:44
@devxplorer Можете ли вы объяснить это больше?
 Bear Brown21 сент. 2017 г., 22:06
какCategory с участием"added": false будет в вашем запросе? какая у тебя логика? ОП получить его поadded_f = categories.extra(select={'added': '0'}).exclude(outfits__pk=obj.pk)
 devxplorer22 сент. 2017 г., 09:49
@JohnBaek, пожалуйста, смотрите комментарий выше, и скажите, пожалуйста, вы пробовали это, он дал правильные результаты?
 Bear Brown22 сент. 2017 г., 11:10
@devxplorer Я проверил ваше решение, это неправильно,репо для теста
 devxplorer22 сент. 2017 г., 09:48
@BearBrown ЛЕВО соединит наряды с указанным идентификатором, затем сгруппирует их по категориям и посчитает элементы нарядов для категории. Если у категории нет нарядов, она получит COUNT (outfit_id)> 0 как ложное. Но, возможно, я не до конца понял, чего хочет автор

Ваш ответ на вопрос