Django Rest 订购自定义

Posted

技术标签:

【中文标题】Django Rest 订购自定义【英文标题】:Django Rest Ordering custom 【发布时间】:2017-04-18 10:18:08 【问题描述】:

我正在使用 django rest 框架,我想使用自定义方法订购。

所以,当我调用这个网址时,例如:http://127.0.0.1:8000/api/sets/?ordering=partMissing

可以调用自定义方法,因为我想订购 sn-p 缺少的零件数量。我计算了多对多字段中部分的总和。

【问题讨论】:

【参考方案1】:

我有非常简单的 POC,应该可以让您实施更复杂的解决方案。

views.py:

from rest_framework import viewsets

from ordering_test.models import Test
from ordering_test.ordering import MyCustomOrdering
from ordering_test.serializers import TestSerializer

class TestViewSet(viewsets.ModelViewSet):
    queryset = Test.objects.all()
    serializer_class = TestSerializer
    filter_backends = (MyCustomOrdering,)

ordering.py:

from rest_framework.filters import OrderingFilter

class MyCustomOrdering(OrderingFilter):

    allowed_custom_filters = ['testMethod']

    def get_ordering(self, request, queryset, view):
        """
        Ordering is set by a comma delimited ?ordering=... query parameter.

        The `ordering` query parameter can be overridden by setting
        the `ordering_param` value on the OrderingFilter or by
        specifying an `ORDERING_PARAM` value in the API settings.
        """
        params = request.query_params.get(self.ordering_param)

        if params:
            fields = [param.strip() for param in params.split(',')]
            # care with that - this will alow only custom ordering!
            ordering = [f for f in fields if f in self.allowed_custom_filters]
            if ordering:
                return ordering

        # No ordering was included, or all the ordering fields were invalid
        return self.get_default_ordering(view)

    def filter_queryset(self, request, queryset, view):

        ordering = self.get_ordering(request, queryset, view)
        if ordering:
            # implement a custom ordering here
            ordering = ['-id']

        if ordering:
            return queryset.order_by(*ordering)

        return queryset

models.pyserializers.py 很简单,但我仍将它们包括在这里:

models.py:

from django.db import models

class Test(models.Model):
    test = models.CharField(max_length=120)
    test1 = models.CharField(max_length=120)

serializers.py:

from rest_framework import serializers

from ordering_test.models import Test

class TestSerializer(serializers.ModelSerializer):

    class Meta:
        model = Test
        fields = ('test', 'test1')

编码愉快!

【讨论】:

我把它留在这里,因为这就是我要找的东西:外键查找...gist.github.com/sainipray/750820b6ece1f81e022cbab56e68174c 这不再适用于 Django 4.0 @AdrianGonzalez 猜猜,我需要更新它:) @opalczynski 我最终使用了这个答案***.com/a/32860854/6929045 它工作得很好,你也可以将它导入到你的views.py中的filter_backends。【参考方案2】:

我认为 opalczynski 的解决方案更简单的方法是为自定义排序引入一个新字段:

from django import forms

import django_filters
from rest_framework import serializers

from .models import MyModel


class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = ('field1',)


class CustomOrderingFilter(django_filters.FilterSet):
    order_by = django_filters.BooleanFilter(
        widget=forms.HiddenInput(),
        method='filter_order_by',
    )

    class Meta:
        model = MyModel
        fields = [
            'order_by'
        ]

    def filter_order_by(self, queryset, name, value):
        if value:
            return self.Meta.model.objects.filter(
                id__in=queryset.values_list('id', flat=True)
            ).order_by(value)

        return queryset

class TestViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    filter_class = CustomOrderingFilter

然后您可以轻松地按您想要的任何字段排序:example.com/api/mymodel/?order_by=partMissing

在我的示例中,我使用了固定模型字段,但您可以在 CustomOrderingFilter 上的 filter_order_by 方法中更改您的排序方式。只需将其更改为您想要的逻辑,但请确保使用.filter(=queryset.values_list('id', flat=True)) 以确保正在使用设置的其他过滤器。

【讨论】:

以上是关于Django Rest 订购自定义的主要内容,如果未能解决你的问题,请参考以下文章

Django-Rest-Framework 系统检查自定义 HTTP 标头(应用程序 - 令牌)

Django Rest Framework 自定义身份验证

如何在 Django REST 框架中为多对多字段定义“IsOwner”自定义权限?

Django rest 框架 JWT 和自定义身份验证后端

Django REST Framework 自定义字段验证

python 使用Django Rest Framework在Django中自定义用户实现