0

I'm using Django with the REST Framework. I'm defining an APIView and in it, I create an ORM object using create(). One of the fields I pass the create function is failing, saying it's not a valid keyword argument. This is a new field I'm adding. The field exists in the model and the serializer. Another similar new field is NOT failing.

Traceback:

Internal Server Error: /api/new_thing
Traceback (most recent call last):
  File "/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/local/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "/other_app/rest_apis.py", line 336, in post
    flag=false
  File "/local/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/local/lib/python2.7/site-packages/django/db/models/query.py", line 346, in create
    obj = self.model(**kwargs)
  File "/local/lib/python2.7/site-packages/django/db/models/base.py", line 480, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'doohickeys' is an invalid keyword argument for this function

API View:

class NewThing(APIView):

    renderer_classes = (JSONRenderer,)
    serializer_class = StuffSerializer

    @detail_route(methods=['POST'])
    def post(self, request, pk, format=None):
        # do stuff
        whatsits_list = [] # list of ORM objects
        doohickeys_list = [] # list of ORM objects
        thing = Thing.objects.create(
            whatsits=whatsits_list, # this is not failing
            doohickeys=doohickeys_list, # this is failing
            flag=false
        )
        # return some stuff

Model:

from django.db import models
from other_app.models import Doohickey, Whatsit

class Thing(models.Model):
    whatsits = models.ManyToManyField('other_app.Whatsit', related_name='things', blank=True)    
    doohickeys = models.ManyToManyField('other_app.Doohickey', related_name='things', blank=True)
    flag = models.BooleanField(default=True)

Serializer:

class StuffSerializer(serializers.ModelSerializer):
    doohickeys = serializers.PrimaryKeyRelatedField(queryset=Doohickey.objects.all(), many=True, allow_empty=True)

    class Meta:
        model = Stuff
        fields = ('id',
                  'doohickeys',
                  'whatsits',
                  'public',
        )

Any idea why I'm getting an error on the doohickey key? I've tried using a debugger to trace through the code and it looks like it's an exception being caught by the dispatch() function in the REST framework APIView class.

Thanks!

4
  • Your indenting is broken. Please fix. Commented Mar 2, 2018 at 1:40
  • Please update code in "/other_app/rest_apis.py", line 336, in post Commented Mar 2, 2018 at 2:00
  • did you tried to create Thing instance without providing a value in your views.py ? Commented Mar 2, 2018 at 4:04
  • @ykh line 336 in /other_app/rest_apis.py is the flag=false line in the view (in post()). Sorry, I realize now that wasn't obvious. Commented Mar 3, 2018 at 7:05

1 Answer 1

2

You can't use a many-to-many field until the object is saved, because it's really a through table that uses the IDs of the objects on each side. So create the object first, then add the doohickeys.

thing = Thing.objects.create(...)
thing.doohickeys.add(*doohickeys_list)

Note though what you're doing is quite odd. The whole point of django-rest-framework is that you use the serializer, which takes care of all this logic for you - you have defined a serializer but you're not using it, you seem to be bypassing that completely.

Sign up to request clarification or add additional context in comments.

1 Comment

To give a little more context, the serializer / endpoint is for the Stuff object whereas this particular part of the view is actually saving a Thing. We then fire off a celery task to process Thing and turn it into a Stuff. I suppose it might make more sense to have this endpoint use a Thing serializer, since our endpoint's ideal return value is a Thing id not a Stuff id. Thanks for the help & feedback! I updated my code per your suggestion and it works great.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.