Reputation: 637
I'm creating a delete method in a DRF API, by passing parameters, but I don't know how to pass correctly an orientdb @rid.
I have a relationship in orientdb called "worksat", in OrientDB Studio i can see the @rid with the structure name like #:, i.e: "#33:1" is the @rid of a worksat relationship record.
So I need to pass that string in my DRF URL api relationship:
http://127.0.0.1:8000/api/oworksat/
But passing like:
http://127.0.0.1:8000/api/oworksat/#33:1
I see GET request, with the message below (I expect to see DELETE):
Allow: GET, POST, HEAD, OPTIONS
If a pass a simple number:
http://127.0.0.1:8000/api/oworksat/1
Then I see DELETE request (obviously "1" doesn't exist):
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
The interesting thing is that by accesing from swagger api, in the DELETE method, if I a pass in the ID of the request "#33:1", it works, the api call to my destroy method and recieve in kwargs: kwargs = {'pk': '#33:1'}
.
How can I reach that behavior from DRF api?
Edited: This is my temporal solution to implement my destroy method, but obviously this only works in Swagger UI, by passing @rid in the request.
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)
Upvotes: 0
Views: 152
Reputation: 398
I assume that when speaking about not being able to delete or see "Delete" button, you talk about Django Rest Framework browsable API.
When you access your API through DRF browsable API you get list of objects when you navigate to for example http://127.0.0.1:8000/api/oworksat/
. This is the "list endpoint" and it doesn't support DELETE
.
Delete button will be there when you access "detail endpoint" of single object, for example: http://127.0.0.1:8000/api/oworksat/123
.
In your case however when you try to pass OrientDB @RID
as object ID, browser thinks you want to get to list endpoint. This is because in urls everything after #
is called fragment and this is not passed to server. So when you navigate to http://127.0.0.1:8000/api/oworksat/#1:23
browser actually requests page from http://127.0.0.1:8000/api/oworksat/
and thus gives you the list endpoint without delete button.
Why Swagger then works?
Swagger works probably because the request is not made the same way as browsers normally load pages. Swagger makes Ajax request to your API when you click the Delete button and thus the fragment part is not stripped from your url. Swagger also probably url encodes the value you type into UI and this would transform #1:22
to %231%3A22
and thus remove #
which causes our problem. DRF then knows how to url decode the url automatically and ends up with correct looking ID.
Example of request Swagger probably does:
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"));
How to fix this?
Your API probably works correctly when @RID
is url encoded and Ajax request is made. It just doesn't work with DRF browsable API.
However to make it nicer to work with for your users and also to make DRF Browsable API to work I would remove #
from the ID's when they are serialized through your API. Users would then make requests to urls like http://127.0.0.1:8000/api/oworksat/1:23
. Of course by doing it like this you would then need to prepend the client provided id with #
before passing it to OrientDB query.
Upvotes: 1