如何从序列化器字段订购 django rest 框架查询集?

Posted

技术标签:

【中文标题】如何从序列化器字段订购 django rest 框架查询集?【英文标题】:How to order django rest framework queryset from serializer field? 【发布时间】:2018-01-01 04:35:42 【问题描述】:

如何从序列化器字段订购 Django QuerySet?由于字段太复杂,我无法使用annotate 订购QuerySet,也无法将值存储在模型中。

编辑:

序列化器

class DrinkListModelSerializer(serializers.ModelSerializer):
    count_need = serializers.SerializerMethodField()
    url = drink_detail_url

    class Meta:
        model = Drink
        fields = [
            'name',
            'count_need',
            'thumbnail',
            'url'
        ]

    def get_count_need(self, obj):
        drink_ingredient_qs = obj.ingredients.all()
        user = self.context['request'].user
        user_qs = User.objects.filter(username=user.username)
        if user_qs.exists() and user_qs.count() == 1:
            user_obj = user_qs.first()
            user_ingredient_qs = user_obj.ingredient_set.all()
            return (user_ingredient_qs & drink_ingredient_qs).count()
        return 0

型号:

class Drink(models.Model):
    name                = models.CharField(max_length = 1000, null=True, blank=True)
    ingredients         = models.ManyToManyField(Ingredient, blank=True)
    user                = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)

class Ingredient(models.Model):
    name                = models.CharField(max_length = 1000)
    ingredient_category = models.ForeignKey(Category, null=True, blank=True)
    slug                = models.SlugField(max_length=255, unique=True)
    user                = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)

查看

class DrinkListAPIView(ListAPIView):
serializer_class = DrinkListModelSerializer
pagination_class = LargeResultsSetPagination
permission_classes = [AllowAny]

def get_queryset(self, *args, **kwargs):
    user = self.request.user
    qs = Drink.objects.all()
    userQuery = self.request.GET.get('user')
    query = self.request.GET.get("q")
    filters = self.request.GET.getlist('filter')
    if query:
        qs = qs.filter(name__icontains=query)
    elif filters:
        qs = qs.filter(playlist__name__iexact=filters[0])
        for filter in filters[1:]:
            qs = qs | Drink.objects.filter(playlist__name__iexact=filter)
    elif userQuery and user.is_authenticated():
        qs = qs.filter(user=user)
    return qs.order_by('-timestamp')

目前,我正在按时间戳对查询集进行排序,因为它在它自己的模型中,但我需要按序列化程序的一部分“count_need”对其进行排序。我尝试做类似qs = qs.annotate(count_need=Count('ingredients' & user_ingredient_qs)).order_by(count_need) 的事情,但这显然行不通,因为这里的“成分”只是一个字符串,而不是饮料的成分查询集。

【问题讨论】:

能否提供您的模型、序列化程序和视图。 我刚刚编辑了原帖 【参考方案1】:

一种可能行之有效的方法是在列表序列化程序上实现和自定义to_representation

def to_representation(self, data):
    iterable = data.all() if isinstance(data, models.Manager) else data

    iterable = sorted(iterable, key=lambda x: x.count_need)

    return [
        self.child.to_representation(item) for item in iterable
    ]

【讨论】:

嗯,我刚试过,我在排序的行上得到“Typeerror:Drink object is not iterable”,有什么建议吗? 看起来你只是将单个实例传递给序列化程序,请尝试在调用初始化序列化程序时添加many=True

以上是关于如何从序列化器字段订购 django rest 框架查询集?的主要内容,如果未能解决你的问题,请参考以下文章

django rest 框架:从序列化器 validate() 方法设置字段级错误

如何使用 django-rest-framework 中的序列化器将相似数据合并到自定义字段中?

如何获取主键相关字段嵌套序列化器django rest框架的所有值

如何在 django rest 框架中为枚举字段创建序列化程序

我可以将单个 Django 模型字段拆分为多个 Django Rest Framework 序列化器字段吗?

django-rest-framework 序列化器在多个视图中的不同字段