【问题标题】:How to use "where" clause in curl?如何在 curl 中使用“where”子句?
【发布时间】:2020-11-30 09:04:15
【问题描述】:

我有一个 API 端点来获取用户添加的所有项目,它返回一个用户添加的所有对象的 JSONArray。

curl 127.0.0.1:8000/api/products/ -H "Authorization: Token xxxxxxxxx"

响应看起来像这样:

[{"url":"http://127.0.0.1:8000/api/products/18/","item_name":"ABC","barcode":"","item_price":5,"usr":"http://127.0.0.1:8000/auth/users/73/"},
{"url":"http://127.0.0.1:8000/api/products/19/","item_name":"PQR","barcode":"123456","item_price":85,"usr":"http://127.0.0.1:8000/auth/users/73/"},...]

现在,我只想检索条形码值为 123456 的对象,即具有“item_name:PQR”的对象。 因此,我尝试在 curl 中使用 'WHERE' 子句,如下所示:

curl 127.0.0.1:8000/api/products?barcode=123456 -H "Authorization: Token xxxxxxxxx"

我收到的是 301 响应,而不是合适的对象。据我所知,3xx 范围内的响应代码意味着可以选择一个的多个响应。 解决此问题的解决方法是什么? 预期输出:

[{"url":"http://127.0.0.1:8000/api/products/19/","item_name":"PQR","barcode":"123456","item_price":85,"usr":"http://127.0.0.1:8000/auth/users/73/"}]
(or)
{"url":"http://127.0.0.1:8000/api/products/19/","item_name":"PQR","barcode":"123456","item_price":85,"usr":"http://127.0.0.1:8000/auth/users/73/"}

我为端点设置的模型视图:
class ProductViewSet(viewsets.ModelViewSet):

    permission_classes = (IsAuthenticated,)
    queryset = ProductModel.objects.all()
    serializer_class = ProductSerializer

    def get_queryset(self):

        user = self.request.user
        queryset = super().get_queryset()
        queryset = queryset.filter(usr=user)
        return queryset

提前致谢。

【问题讨论】:

    标签: json django api curl endpoint


    【解决方案1】:

    HTTP 301 状态是 Moved Permanently 重定向状态响应代码。

    您的网址可能以斜杠('/')结尾,而您没有在请求中添加它。 Django 有一个名为 APPEND_SLASH 的设置,如果您在设置的中间件列表中有 CommonMiddleware,则默认为 True。此设置将您的请求重定向到附加斜线的 url,在您的情况下将如下所示:

    curl 127.0.0.1:8000/api/products/?barcode=123456 -H "Authorization: Token xxxxxxxxx"
    

    这就是你得到 301 的原因。试试在 url 中附加斜杠。

    对于 REST API 中的 WHERE 子句,您必须确保已在已构建的 REST API 中添加过滤器。您可以通过检查传递的查询参数来过滤视图的 get_queryset 方法中的查询集,或者,如果您使用 DRF,则可以使用 REST 框架提供的过滤器。

    如果您使用 DRF,则可以通过在视图中添加/更新此方法来过滤查询集:

    def get_queryset(self):
        user = self.request.user
        queryset = super().get_queryset()
        barcode = self.request.query_params.get('barcode', None)
        if barcode:
            queryset = queryset.filter(barcode=barcode)
        queryset = queryset.filter(usr=user)
        return queryset
    

    def get_queryset(self):
        filters = {}
        filters['user'] = self.request.user
        queryset = super().get_queryset()
        barcode = self.request.query_params.get('barcode', None)
        if barcode:
            filters['barcode'] = barcode
        queryset = queryset.filter(**filters)
        return queryset
    

    这两个查询集的工作方式相同。

    或者您可以通过将过滤器添加到视图中来在视图中使用过滤器:

    from django_filters.rest_framework import DjangoFilterBackend
    
    class ProductViewSet(viewsets.ModelViewSet):
    
        permission_classes = (IsAuthenticated,)
        queryset = ProductModel.objects.all()
        serializer_class = ProductSerializer
        filter_backends = [DjangoFilterBackend]
        filterset_fields = ['barcode', ]
    
        def get_queryset(self):
    
            user = self.request.user
            queryset = super().get_queryset()
            queryset = queryset.filter(usr=user)
            return queryset
    

    参考资料:

    【讨论】:

    • 你好,最初我尝试在 URL 中附加一个“/”,在这种情况下,整个 JSONArray 被获取,即,该数组未被过滤以仅获取其条形码值为的对象应该是 123456。还有其他解决方法来解决这个问题吗?
    • 是的,您必须确保已在您构建的 REST API 中添加了过滤器。您可以通过检查传递的查询参数来过滤视图的 get_queryset 方法中的查询集,或者,如果您使用 DRF,则可以使用 REST 框架提供的过滤器。
    • 您能否澄清一下您使用的是 DRF 还是其他东西,并发布您的视图代码,以便我可以帮助您并更新答案
    • 如果它回答了您的问题,请检查我的更新答案,您还可以参考 DRF 过滤文档以获得更多帮助。
    • 是的,现在工作得很好。感谢您抽出时间进行适当的更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多