Reputation: 2939
I am designing an API endpoint using Django REST Framework, and would like for it to accept GET and POST methods at the following endpoint:
companies/<company_pk>/membership
as well as DELETE methods at the following endpoint:
companies/<company_pk>/membership/<membership_pk>
There are two relevant models: Company
and CompanyMembership
. Each user can be a member of one or more companies,which is represented by an instance of CompanyMembership
, which linked by a FK to Company
.
I've created the appropriate GET and POST requests, but am having trouble with the DELETE requests -- it seems that the destroy
method within my view is missing the membership_pk
parameter, whether or not I define it within my URLs. How can I have my view accept DELETE requests which delete instances of CompanyMembership
, which are identified by the membership_pk
given in the URL?
urls.py
...
url(r'^companies/(?P<company_pk>[0-9]+)/membership', include(company_urls.company_membership_router.urls,
namespace='company_memberships')),
...
views.py
class CompanyMembershipViewSet(viewsets.ModelViewSet):
"""
A ViewSet for creating, retrieving, and deleting CompanyMemberships.
"""
queryset = CompanyMembership.objects.all()
serializer_class = CompanyMembershipSerializer
lookup_url_kwarg = 'company_pk'
def get_queryset(self):
uid = self.kwargs.get(self.lookup_url_kwarg)
memberships = CompanyMembership.objects.filter(company_id=uid)
return memberships
def create(self, request, company_pk):
"""
Custom create method since company_pk does not have to be sent
explicitly within request.data
Returns: instance of rest_framework Response.
"""
EXISTING_USER_ERROR = {'non_field_errors':
['The fields user, company must make a unique set.']
}
data = {
'user': request.data['user'],
'company': company_pk
}
serializer = CompanyMembershipSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
if serializer.errors == EXISTING_USER_ERROR:
return Response(serializer.errors, status=settings.ADDITIONAL_HTTP_STATUS_CODES['422_UNPROCESSABLE_ENTITY'])
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def destroy(self, request, **kwargs):
company_membership = self.get_object(pk=membership_pk)
company_membership.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
routers.py
from rest_framework import routers
from .views import CompanyViewSet, CompanyMembershipViewSet
company_router = routers.DefaultRouter()
company_membership_router = routers.DefaultRouter()
company_router.register(r'^', CompanyViewSet)
company_membership_router.register(r'^', CompanyMembershipViewSet)
Upvotes: 1
Views: 3216
Reputation: 47886
The company membership router generates the following urls:
companies/<company_pk>/membership/ # for handling list requests
companies/<company_pk>/membership/<pk>/ # for handling detail requests
You can access the membership_pk
using the pk
url kwarg .
Also, you have incorrectly defined lookup_url_kwarg
field in your viewset. This kwarg
is used by DRF to retrieve the object using get_object()
method. You are not getting object because it is trying to perform lookup with pk
as company_pk
url kwarg value instead of pk
value.
Upvotes: 1