web-dev-qa-db-ja.com

Django残りのフレームワークの複数のlookup_fields

ルックアップフィールドとしてidを使用して歴史的に機能する複数のAPIがあります。

/api/organization/10

私はそれらのAPIを消費するフロントエンドを持っています。

私は新しいインターフェースを構築していますが、いくつかの理由で、IDの代わりにスラッグを使用したいと思います。

/api/organization/my-orga

APIはDjango Rest Frameworkで構築されています。ルックアップフィールドの変更を除いて、APIの動作は同じままである必要があります。

APIがslugpkの両方で機能するようにするソリューションはありますか?これらの2つのパスは、同じ結果をもたらすはずです。

/api/organization/10
/api/organization/my-orga

これが私のAPI定義です:

# urls.py
router = DefaultRouter()
router.register(r'organization', Organization)
urlpatterns = router.urls

#view.py
class Organization(viewsets.ModelViewSet):
    queryset = OrganisationGroup.objects.all()
    serializer_class = OrganizationSerializer

# serializer.py
class OrganizationSerializer(PermissionsSerializer):
    class Meta:
        model = Organization

ご協力いただきありがとうございます。

10
Alex Grs

これを試して

from Django.db.models import Q
import operator
class MultipleFieldLookupMixin(object):
    def get_object(self):
        queryset = self.get_queryset()             # Get the base queryset
        queryset = self.filter_queryset(queryset)  # Apply any filter backends
        filter = {}
        for field in self.lookup_fields:
            filter[field] = self.kwargs[field]
        q = reduce(operator.or_, (Q(x) for x in filter.items()))
        return get_object_or_404(queryset, q)

次に表示

class Organization(MultipleFieldLookupMixin, viewsets.ModelViewSet):
    queryset = OrganisationGroup.objects.all()
    serializer_class = OrganizationSerializer
    lookup_fields = ('pk', 'another field')

お役に立てれば。

9
itzMEonTV
class MultipleFieldLookupMixin(object):
    """
    Apply this mixin to any view or viewset to get multiple field filtering
    based on a `lookup_fields` attribute, instead of the default single field filtering.
    """

    def get_object(self):
        queryset = self.get_queryset()  # Get the base queryset
        queryset = self.filter_queryset(queryset)
        filter = {}
        for field in self.lookup_fields:
            if self.kwargs[field]:  # Ignore empty fields.
                filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)  # Lookup the object


class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = ('account', 'username')
3
D.Wang

retrieveメソッドをオーバーライドし、pkフィールドの値を任意のパターンと照合することで、同様の問題を解決しました。たとえば、数字だけで構成されている場合です。

def retrieve(self, request, *args, **kwargs):
    if kwargs['pk'].isdigit():
        return super(Organization, self).retrieve(request, *args, **kwargs)
    else:
        # get and return object however you want here.
2
Hikmat G.

基本的な答えは、これは適切なREST/API設計ではなく、DRFが可能にするものではないということだと思います。

1
Evan Zamir

公式ドキュメントには、この例があります https://www.Django-rest-framework.org/api-guide/generic-views/#creating-custom-mixins

また、urls.pyを変更して、同じビューの新しいルートを新しいフィールド名で追加する必要があります。

0

get_object(self)メソッドをオーバーライドするのが最善の方法だと思います

class Organization(generics.RetrieveAPIView):
    serializer_class = OrganizationSerializer
    queryset = Organization.objects.all()
    multiple_lookup_fields = ['pk', 'slug']

    def get_object(self):
        queryset = self.get_queryset()
        filter = {}
        for field in self.multiple_lookup_fields:
            filter[field] = self.kwargs[field]

        obj = get_object_or_404(queryset, **filter)
        self.check_object_permissions(self.request, obj)
        return obj
0
giveJob