i'm trying write simple update view django rest application, cannot figure out how it. i've gotten range of errors 403 500.
basically, have table 'foo' , want set 'active' field 'true' 'false'. here's view have currently:
class disablefoo(generics.updateapiview): permission_classes = (permissions.isauthenticated,) serializer_class = fooserializer queryset = foo.objects.all() def perform_update(self, serializer): queryset = foo.objects.filter(pk = self.request.data['id']) queryset.update(active = false)
however, results in assertionerror:
expected view disablefoo called url keyword argument named "pk". fix url conf, or set '.lookup_field' attribute on view correctly.
you should not send id
of row want update request.data within url
.
so if hitting right like:
/api/foo/
try
/api/foo/<id>/
of course won't enough. should consider few more things.
you hooking on perform_update
method. that's not correct. perform_update
called in order update whole object serializer.save()
, therefore called when serializer.is_valid()
.
this means have send valid foo
object. that's not want. need update single field of foo
object. right approach here use partial_update
. partial_update
used when make patch
request /api/foo/<id>/
so if send patch
request /api/foo/<id>/
active=0
inside request.data drf update object automatically without further code changes. using
class disablefoo(generics.updateapiview): permission_classes = (permissions.isauthenticated,) serializer_class = fooserializer queryset = foo.objects.all()
but expose model fields update. can override partial_update
method so:
def partial_update(self, request, *args, **kwargs): instance = self.get_object() instance.active = false instance.save(update_fields=['active']) return response()
another approach
drf support creation of extra extra-actions via @detail_route
, @list_route
decorators.
you can use @detail_route
create custom disable action. consider following peace of code:
class fooviewset(viewsets.genericviewset): queryset = foo.objects.all() serializer_class = fooserializer @detail_route(methods=['post']) def disable(self, request, pk=none): instance = self.get_object() instance.active = false instance.save(update_fields=['active']) return response('done')
making post
request /api/foo/<id>/disable
call disable
method wrote , disable foo
instance under <id>
.
this way can escape requirement use patch
request method.