TypeError: post() takes 1 positional argument but 2 were given

Question:

I have my model class:

class Subscription(models.Model):
    email = models.EmailField(max_length=250, unique=True)

    def __str__(self):
        return self.email

and my View:

class SubscriptionView(APIView):
    queryset = Subscription.objects.all()

    def post(request):
        email = request.data.get('email')
        print(email)
        save_email = Subscription.objects.create(email=email)
        save_email.save()

        return Response(status=status.HTTP_201_CREATED)

My model only takes in 1 field which is the email. Not sure why I keep getting ‘TypeError: post() takes 1 positional argument but 2 were given’.

Asked By: jdez

||

Answers:

Your post is a method, so the first parameter is self:

class SubscriptionView(APIView):
    queryset = Subscription.objects.all()

    def post(self, request):
        email = request.data.get('email')
        Subscription.objects.create(email=email)
        return Response(status=status.HTTP_201_CREATED)

It is however quite seldom that one implements a post method itself. Usually you work for example with a CreateAPIView [drf-doc], and one can let the serializer, etc. handle all the work.

Answered By: Willem Van Onsem

post is an Instance method of Class SubscriptionView, while invoking an Instance method Python automatically passes an object reference of that class. So you need to receive that object reference in your instance method.

You didn’t receive that object reference in your post method that’s why Python Interpreter showing you:

TypeError: post() takes 1 positional argument but 2 were given

but 2 were given Because Python calling post like, post(SubscriptionView(), request) but you receive only request

You can receive object reference using any name but using self is standard.

class SubscriptionView(APIView):
    queryset = Subscription.objects.all()

    def post(self, request):
        email = request.data.get('email')
        Subscription.objects.create(email=email)
        return Response(status=status.HTTP_201_CREATED)
Answered By: Omar