【问题标题】:What is the correctly way to pass an orientdb @rid as a parameter, to DELETE request in django rest framework?将 orientdb @rid 作为参数传递给 django rest 框架中的 DELETE 请求的正确方法是什么?
【发布时间】:2019-10-30 03:21:16
【问题描述】:

我正在通过传递参数在 DRF API 中创建删除方法,但我不知道如何正确传递 orientdb @rid。

我在 orientdb 中有一个名为“worksat”的关系,在 OrientDB Studio 中,我可以看到 @rid 的结构名称类似于 #:,即:“#33:1”是 @rid工作卫星关系记录。

所以我需要在我的 DRF URL api 关系中传递该字符串:

http://127.0.0.1:8000/api/oworksat/

但是像这样传递:

http://127.0.0.1:8000/api/oworksat/#33:1

我看到 GET 请求,消息如下(我希望看到 DELETE): Allow: GET, POST, HEAD, OPTIONS

如果传递一个简单的数字:

http://127.0.0.1:8000/api/oworksat/1

然后我看到DELETE请求(显然“1”不存在):

HTTP 404 Not Found
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS

api.py:

class OWorksAtViewSet(viewsets.ModelViewSet):

    queryset = graph.oworksat.query()
    serializer_class = OWorksAtSerializer
    permission_classes = [
        permissions.AllowAny
    ]

    def destroy(self, request, *args, **kwargs):
        print ("destroy")
        import pdb;pdb.set_trace()

urls.py:

from django.conf.urls import include, url
from rest_framework import routers
from .api import (OWorksAtViewSet)
from rest_framework_swagger.views import get_swagger_view

router = routers.DefaultRouter()
router.register('api/oworksat', OWorksAtViewSet, 'oworksat')

schema_view = get_swagger_view(title='Swagger Documentation')

urlpatterns = [
    url(r'^swagger/$', schema_view)
]

urlpatterns += router.urls

有趣的是,通过从 swagger api 访问,在 DELETE 方法中,如果我传入请求“#33:1”的 ID,它会起作用,api 调用我的 destroy 方法并在 kwargs 中接收:kwargs = {'pk': '#33:1'}

如何从 DRF api 实现该行为?

已编辑: 这是我实现销毁方法的临时解决方案,但显然这只适用于 Swagger UI,通过在请求中传递 @rid。

from rest_framework import status
from rest_framework.response import Response
from core.pyorient_client import *

class OFriendsViewSet(viewsets.ModelViewSet):

    def destroy(self, request, *args, **kwargs):
        client = orientdbConnection()

        client.command("delete edge ofriends where @rid = '" + kwargs['pk'] + "'")

        return Response(status=status.HTTP_204_NO_CONTENT)

【问题讨论】:

  • 您是否使用任何 REST 客户端在第一个场景中发出请求?它是否达到了代码?您在这里遇到的错误是什么?如果您使用/#33:1/ 拨打DELETE 会发生什么?
  • 我正在使用 rest 框架来提出请求。通过传递127.0.0.1:8000/api/oworksat/#33:1,响应为 200,但使用 GET 方法(所以它没有到达 destroy 方法),我需要允许 DELETE 方法的行为
  • 所以在你的rest框架客户端,你看不到DELETE方法对吧?
  • 我可以看到它,但不是通过在查询字符串中传递#33:1,传递#33:1 我只看到 GET 和 POST 方法

标签: django python-3.x django-rest-framework orientdb pyorient


【解决方案1】:

我假设当谈到无法删除或看到“删除”按钮时,您谈论的是 Django Rest Framework 可浏览 API。

当您通过 DRF 可浏览 API 访问您的 API 时,您会在导航到例如 http://127.0.0.1:8000/api/oworksat/ 时获得对象列表。这是“列表端点”,它不支持DELETE

当您访问单个对象的“详细端点”时,将出现删除按钮,例如:http://127.0.0.1:8000/api/oworksat/123

但是,在您的情况下,当您尝试将 OrientDB @RID 作为对象 ID 传递时,浏览器会认为您想要列出端点。这是因为在 urls 中,# 之后的所有内容都被称为片段,并且不会传递给服务器。因此,当您导航到 http://127.0.0.1:8000/api/oworksat/#1:23 时,浏览器实际上会从 http://127.0.0.1:8000/api/oworksat/ 请求页面,从而为您提供不带删除按钮的列表端点。

为什么 Swagger 会起作用?

Swagger 之所以有效,可能是因为发出请求的方式与浏览器通常加载页面的方式不同。当您单击“删除”按钮时,Swagger 会向您的 API 发出 Ajax 请求,因此片段部分不会从您的 url 中删除。 Swagger 也可能 url 将您键入的值编码到 UI 中,这会将#1:22 转换为%231%3A22 并因此删除导致我们问题的#。然后 DRF 知道如何自动对 url 进行 url 解码并最终得到正确的 ID。

请求 Swagger 的示例可能会:

function deleteData(url, item) {
  return fetch(url + '/' + item, {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  .then(response => console.log(response.json()));
}

deleteData("http://127.0.0.1:8000/api/oworksat/", encodeURIComponent("#1:23"));

如何解决这个问题?

@RID 被 url 编码并发出 Ajax 请求时,您的 API 可能会正常工作。它只是不适用于 DRF 可浏览 API。

但是,为了让您的用户更好地使用它并让 DRF Browsable API 正常工作,当通过您的 API 对 ID 进行序列化时,我将从 ID 中删除 #。然后用户会向http://127.0.0.1:8000/api/oworksat/1:23 之类的网址发出请求。当然,通过这样做,您需要在客户端提供的 id 前面加上 #,然后再将其传递给 OrientDB 查询。

【讨论】:

  • 感谢您的详细解释,非常感谢。问题是我无法控制 rid 存储在 OrientDB 中的方式,因为该字段是 pk 的类比,所以它是自动生成的,因此我无法在没有 # 的情况下序列化 rid 以按照您的建议工作。无论如何,我必须在我的 OrientDB 方法中使用原始查询(我编辑了我的问题),如下面stackoverflow.com/a/56621592/6796652 但显然,这个解决方案只适用于招摇 UI
猜你喜欢
  • 1970-01-01
  • 2011-11-24
  • 1970-01-01
  • 2016-01-22
  • 2022-07-04
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多