Фильтр упорядочения Django Rest Framework, порядок по длине вложенного списка

Я использую OrderingFilter глобально через settings.py, и это прекрасно работает.

Теперь я хотел бы заказать размер вложенного списка из ManyToManyField. Возможно ли это с OrderingFilter по умолчанию?

Если нет, есть ли способ сделать это с помощью пользовательского фильтра, сохраняя при этом параметр запроса ordering в URL-адресе (http://example.com/recipes/?ordering=). Ради консистенции.

О, и ManyToManyField — это сквозная таблица.

Это мои models.py:

class Recipe(models.Model):
    name = models.CharField(max_length=255)
    cook_time = models.FloatField()
    ingredients = models.ManyToManyField(IngredientTag, through=Ingredient)

My serializers.py:

class IngredientTagSerializer(serializers.ModelSerializer):
    class Meta:
        model = IngredientTag
        fields = ('id', 'label')

class IngredientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ingredient
        fields = ('amount', 'unit', 'ingredient_tag')
        depth = 1

class RecipeSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(source='ingredient_set', many=True)

    class Meta:
        model = Recipe
        fields = ('id', 'url', 'name', 'ingredients', 'cook_time')
        read_only_fields = ('owner',)
        depth = 2

И мой views.py:

class RecipeViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows recipes to be viewed or edited.
    """
    queryset = Recipe.objects.all().order_by()
    serializer_class = RecipeSerializer
    permission_classes = (DRYPermissions,)
    ordering_fields = ('cook_time',) #Need ingredient count somewhere?

Спасибо!


person Robert Broersma    schedule 15.09.2016    source источник


Ответы (1)


Пытаться:

class RecipeSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(source='ingredient_set', many=True)
    ingredients_length = serializers.SerializerMethodField()

    class Meta:
        model = Recipe
        fields = ('id', 'url', 'name', 'ingredients', 'cook_time')
        read_only_fields = ('owner',)
        depth = 2

    def get_ingredients_length(self, obj):
        return obj.ingredients.count()

Затем упорядочить по ингредиентам_длине

РЕДАКТИРОВАТЬ

В model.py попробуйте это:

@property
    def ingredient_length(self):
        return self.ingredient_set.count()
person Windsooon    schedule 15.09.2016
comment
Прежде всего, вы не можете использовать len для obj.ingredients. Вы должны использовать obj.ingredients.all() или что-то в этом роде, верно? Во-вторых, это не работает. Я получаю FieldError: Cannot resolve keyword u'ingredients_length' into field. Кажется, я где-то читал, что OrderingFilter работает на уровне базы данных, поэтому вычисляемые поля Python не работают? - person Robert Broersma; 15.09.2016
comment
Спасибо за помощь. В обоих случаях я могу заставить поле отображаться в результатах моего API, но я все равно получаю FieldError при попытке сортировки по нему. Является ли мой единственный вариант использовать пользовательский фильтр? - person Robert Broersma; 17.09.2016
comment
Если вы хотите заказать только по многим полям. другое решение, которое вы можете переопределить queryset = Recipe.objects.all() от Дэниела Роузмана stackoverflow.com/questions/4309062/. - person Windsooon; 17.09.2016
comment
Я не уверен, как это мне поможет, но я хотел бы отсортировать и другие поля. - person Robert Broersma; 17.09.2016
comment
Пожалуйста, опубликуйте все сообщение об ошибке, что после FieldError: Не удается преобразовать ключевое слово u'ingredients_length' в поле. выборы какие? - person Windsooon; 17.09.2016
comment
FieldError: Cannot resolve keyword u'ingredients_length' into field. Choices are: carbs_relative, cook_time, energy, fat_relative, id, ingredient, ingredients, meal, name, nutritions, owner, owner_id, protein_relative, recipenutrition, source_img, source_url, tags. Это набор полей, которые у меня есть в моей модели, которые я пропустил в исходном вопросе для простоты :) - person Robert Broersma; 17.09.2016