簡體   English   中英

Django Rest 訂購定制

[英]Django Rest Ordering custom

我正在使用 django rest 框架,我想使用自定義方法進行訂購。

所以,當我調用這個 url 例如: http://127.0.0.1:8000/api/sets/?ordering=partMissing

可以調用自定義方法,因為我想用代碼段缺少的零件數進行訂購。 我計算了多對多字段中部分的總和。

我有非常簡單的 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')

快樂編碼!

我認為 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

在我的例子,我用了一個固定的模式場,但你可以改變你的訂購方式filter_order_by的方法CustomOrderingFilter 只需將其更改為您想要的邏輯,但請確保使用.filter(=queryset.values_list('id', flat=True))以確保正在使用設置的其他過濾器。

您可以使用FilterSet進行注釋,然后使用OrderingFilter進行相應的排序。 作為一個優勢,您可以使用OrderingField語法,並且仍然可以同時按多個字段進行排序。

  • /api/?annotate_related={id}&order=subscribed
  • /api/?annotate_related={id}&order=-subscribed
  • /api/?annotate_related={id}&order=-subscribed,-modified

過濾器集:

class YourFilterSet(FilterSet):
    annotate_related = filters.NumberFilter(method="_annotate_related")

    class Meta:
        model = Model

    def _annotate_related(self, queryset, key, value, *args, **kwargs):
        # eg. annotate if user belongs to a certain category
        return queryset.annotate(is_subscribed=Case(When(annotate_related__id=value, then=1), output_field=IntegerField(), default=0))

視圖集:

class YourViewSet(ModelViewSet):
    queryset = Model.objects.all()
    filterset_class = YourFilterSet
    filter_backends = [OrderingFilter, DjangoFilterBackend]
    ordering_fields = [
        "is_subscribed", # order by annotated field
    ]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM