Django-REST:添加 API 以通过另一个字段获取实体的正确方法?

Django-REST: Proper way to add API to get entity via another field?

我是 Python/Django/Django-REST 的超级新手,但我已经设法遵循 tutorial 并创建了我自己的 API,类似于教程。

在我的应用程序中,我有一个名为 Toggle 的模型,其中有一个名为 feature_key.

的唯一字段

按照教程,获取 Toggle 的默认方法是使用 ID,即

http://127.0.0.1:8000/toggles/1/

它在可浏览的 API 页面中显示为可点击的 link。


我的问题是,如何添加另一个端点以通过其 feature_key 直接获得切换?也许是这样的:

http://127.0.0.1:8000/toggles/key/category.key_1/

(我不确定这是不是"correct"设计的方式API)

如何使此端点在可浏览的 API 中可见,以便其他开发人员知道此端点存在?


toggle/views.py:

这几乎和教程的一样view.py

# imports here


@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'users': reverse('user-list', request=request, format=format),
        'toggles': reverse('toggle-list', request=request, format=format)
    })


class ToggleViewSet(viewsets.ModelViewSet):
    queryset = Toggle.objects.all()
    serializer_class = ToggleSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)


class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

toggle/serializers.py:

也类似教程

class ToggleSerializer(serializers.HyperlinkedModelSerializer):
    created_by = serializers.ReadOnlyField(source='created_by.username')
    is_enabled = serializers.BooleanField(initial=True)

    class Meta:
        model = Toggle
        fields = ['url', 'id', 'feature_key', 'description', 'is_enabled', 'created_at', 'created_by']


class UserSerializer(serializers.HyperlinkedModelSerializer):
    toggles = serializers.HyperlinkedRelatedField(many=True, view_name='toggle-detail', read_only=True)

    class Meta:
        model = User
        fields = ['url', 'id', 'username', 'toggles']

toggle/urls.py:

与教程相同

router = DefaultRouter()
router.register(r'toggles', views.ToggleViewSet)
router.register(r'users', views.UserViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

我看了教程...

您可以进行以下更改: urls.py

替换这个

path('toggles/<int:pk>/', views.toggles_function),

有了这个:

path('toggles/<feature_key>/', views.toggles_function),

views.py

@csrf_exempt
def snippet_detail(request, key):
    try:
        snippet = Snippet.objects.get(feature_key=key)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

你可以获得linkhttp://127.0.0.1:8000/toggles/<feature_key of entry>/

如果你想要link这样

http://127.0.0.1:8000/toggles/key/category.key_1/

urls.py

path('toggles/<pk>/<feature_key>/', views.toggles_function),

并在 views.py

@csrf_exempt
    def snippet_detail(request, pk, key):
        try:
            snippet = Snippet.objects.get(feature_key=key) # snippet = Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            return HttpResponse(status=404)

建议

您不需要在 url 中使用来自同一模型的两个字段(如 pk 和 feature_key 两者),如果它们都是唯一字段。您可以从其中任何一个获取实例。