binny
binny

Reputation: 729

TypeError: create() takes 1 positional argument but 2 were given; Django REST Framework

I'm encountering a problem when trying to create a model instance from deserialized/validated data. As shown, a TypeError is raised when the implementation of self.create() is invoked when within Serializer.save(). I can't figure out what the second argument would be that is causing the error. Here is the validated_data argument passed to the function...

{'gender': {'MALE'}, 'size': {'LARGE', 'MEDIUM'}, 'age': {'ADULT', 'BABY'}, 'user': <User: Mock>}

File "C:\...\rest_framework\serializers.py", line 191, in save
    self.instance = self.create(validated_data)
TypeError: create() takes 1 positional argument but 2 were given

tests.py

class TestSetUserPreferences(TestCase):
    '''Verify that an User receives a 201 status code
    when setting preferences on their profile.'''

    @classmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user(
            username="Mock", password="secret"
        )

        cls.credentials = b64encode(b"Mock:secret").decode("ascii")

        cls.user_settings = json.dumps({
            "gender": ["MALE"],
            "size": ["MEDIUM", "LARGE"],
            "age": ["BABY", "ADULT"]
        })

        cls.factory = APIRequestFactory()

    def test_user_preference_settings_success(self):
        request = self.factory.post(
            reverse("user-pref-settings"),
            data=self.user_settings,
            content_type="application/json",
            headers = {
                'HTTP_AUTHORIZATION': f"Basic {self.credentials}"
            }
        )
        force_authenticate(request, self.user)
        response = SetUserPrefView.as_view()(request)
        self.assertEqual(response.status_code, 201)

views.py


class SetUserPrefView(
    GenericAPIView,
    CreateModelMixin,
    RetrieveModelMixin,
    UpdateModelMixin):

    queryset = UserPref.objects.all()
    serializer_class = UserPreferenceSerializer

    def post(self, *args, **kwargs):
        import pdb; pdb.set_trace()
        self.create(self.request, *args, **kwargs)

    def perform_create(self, serializer):
        return serializer.save(user=self.request.user)

serializers.py

class UserPreferenceSerializer(serializers.Serializer):
    gender = serializers.MultipleChoiceField(choices=USER_PREF_DOG_GENDER)
    size = serializers.MultipleChoiceField(choices=USER_PREF_DOG_SIZE)
    age = serializers.MultipleChoiceField(choices=USER_PREF_DOG_AGE)

    def create(self, **validated_data):
        user = UserPref.objects.create(**validated_data)

Upvotes: 0

Views: 1378

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476649

As the error indicates, the create method takes two positional parameters, the data is not passed as named parameters, but in a single dictionary, so you should write this as:

class UserPreferenceSerializer(serializers.Serializer):
    gender = serializers.MultipleChoiceField(choices=USER_PREF_DOG_GENDER)
    size = serializers.MultipleChoiceField(choices=USER_PREF_DOG_SIZE)
    age = serializers.MultipleChoiceField(choices=USER_PREF_DOG_AGE)

    def create(self, validated_data):
        return UserPref.objects.create(**validated_data)

Upvotes: 2

Related Questions