python - Django REST Framework: return 404 (not 400) on POST if related field does not exist? -


i'm developing rest api takes post requests brain-dead software can't patch or else. posts update model objects exist in database.

specifically, i'm posting data objects related field (a slugrelatedfield, poster knows 'name' attribute not 'pk'). however, need return 404 if poster sends data 'name' returns nothing on slugrelatedfield (e.g. related object not exist). i've been through debugger seems drf uses django signals magic way drf it™, return 400 bad request. don't know how modify - only when it's above condition , not true 400-worthy post - 404.

by way, pre_save() in view not executing during execution of failing test.

here's serializer:

class characterizationserializer(serializers.modelserializer):     """     work-in-progress django-rest-framework use.  handles (de)serialization     of data characterization object , vice versa.      see: http://www.django-rest-framework.org/tutorial/1-serialization     """     creator = serializers.field(source='owner.user.username')     sample = serializers.slugrelatedfield(slug_field='name',                                           required=true,                                           many=false,                                           read_only=false)      class meta:         model = characterization         # leaving 'request' out because it's been decided deprecate it. (...maybe?)         fields = ('sample', 'date', 'creator', 'comments', 'star_volume', 'solvent_volume',                   'solution_center', 'solution_var', 'solution_minimum', 'solution_min_stddev',                   'solution_test_len',) 

and here's view pre_save isn't being run in given test (but run in others):

class characterizationlist(generics.listcreateapiview):     queryset = characterization.objects.all()     serializer_class = characterizationserializer     permission_classes = (anonpostallowed,)   # @todo xxx hack braindead poster      def pre_save(self, obj):         # user isn't sent part of serialized representation,         # instead property of incoming request.         if not self.request.user.is_authenticated():             obj.owner = get_dummy_proxyuser()   # done characterizationlist unauthed users can post. @todo xxx hack         else:             obj.owner = proxyuser.objects.get(pk=self.request.user.pk)          # here, we're fed string sample name, need         # actual sample model.         # @todo: failing if doesn't exist?  should         # throw 404, not 400 or 5xx.         # except, code doesn't seem run directly when debugging.         # 400 thrown; drf must bombing out before pre_save?         obj.sample = sample.objects.get(name=self.request.data['sample']) 

and measure, here's failing test:

def test_bad_post_single_missing_sample(self):     url = reverse(self._post_one_view_name)      my_sample_postdict = self.dummy_plqy_postdict.copy()     my_sample_postdict["sample"] = "i_dont_exist_lul"     response = self.rest_client.post(url, my_sample_postdict)     self.asserttrue(response.status_code == 404,                     "expected 404 status code, got %d (%s). content: %s" % (response.status_code, response.reason_phrase, response.content)) 

if put breakpoint in @ self.rest_client.post() call, response has 400 in @ point.

instead of using pre_save why not override post in api view:

def post(self, request, *args, **kwargs):     ...other stuff     try:         obj.sample = sample.objects.get(name=self.request.data['sample'])         ...or whatever other tests want     except:         return response(status=status.http_404_not_found)      response = super(characterizationlist, self).post(request, *args, **kwargs)     return response 

make sure import drf's status:

from rest_framework import status 

also, note want more specific exceptions catch. django's get method return either doesnotexist if nothing matches or multipleobjectsreturned if more 1 object matches. the relevant documentation:

note there difference between using get(), , using filter() slice of [0]. if there no results match query, get() raise doesnotexist exception. exception attribute of model class query being performed on - in code above, if there no entry object primary key of 1, django raise entry.doesnotexist.

similarly, django complain if more 1 item matches get() query. in case, raise multipleobjectsreturned, again attribute of model class itself.


Comments

Popular posts from this blog

google api - Incomplete response from Gmail API threads.list -

Installing Android SQLite Asset Helper -

Qt Creator - Searching files with Locator including folder -