如何从序列化程序字段订购Django Rest Framework queryset? [英] How to order django rest framework queryset from serializer field?

查看:112
本文介绍了如何从序列化程序字段订购Django Rest Framework queryset?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从序列化程序字段订购Django QuerySet ?由于字段太复杂,我无法使用 annotate 来订购 QuerySet ,并且无法将值存储在

How can I order a Django QuerySet from a serializer field? Since the field is too complicated, I couldn't order the QuerySet using annotate and I cannot store the value in the model as well.

编辑:

序列化器

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)的事情,但这显然由于'ingredients'而无效'只是一个字符串,而不是Drink的成分查询集。

Currently, I'm ordering the queryset by timestamp since it is in the model it self, but i need to order it by 'count_need' which is part of the serializer. I tried to do something like qs = qs.annotate(count_need=Count('ingredients' & user_ingredient_qs)).order_by(count_need) but this clearly doesnt work since 'ingredients' is just a string here and not the Drink's ingredient queryset.

推荐答案

一种可行的方法是实现和自定义<列表序列化程序上的code> to_representation :

One way that might work well is to implement and customize to_representation on the list serializer:

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
    ]

这篇关于如何从序列化程序字段订购Django Rest Framework queryset?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆