django-rest-auth error - save() takes 1 positional argument but 2 were given

試著忘記壹切 提交于 2020-01-05 09:22:09

问题


I'm using django-rest-auth with a custom user model, registration view and serializer. What I'm trying to achieve is an email login instead of username. The api view shows correctly but when I post, I get the error:

TypeError at /rest-auth/registration/
save() takes 1 positional argument but 2 were given

this is the traceback: http://dpaste.com/2FR3DZY

serializer.py

class CustomUserSerializer(serializers.ModelSerializer):
"""Serializer for User objects."""

    class Meta:
        model = models.User
        fields = ('id', 'email', 'name', 'password')
        extra_kwargs ={'password': {'write_only': True}}

    def create(self, validated_data):
        """Create and return a new User."""

        user = models.User(
            email=validated_data['email'],
            name=validated_data['name'] 
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

views.py

class CustomRegistrationsView(RegisterView):
    serializer_class = CustomUserSerializer

urls.py

path('rest-auth/registration/', CustomRegistrationsView.as_view(), name='rest_register'),   
path('rest-auth/', include('rest_auth.urls')),

models.py

class UserManager(BaseUserManager):
"""Helps Django work with our custom user model."""

    def create_user(self, email, name, password=None):
        """Creates a new user object."""

        if not email:
            raise ValueError('Users must have an email address.')

        email = self.normalize_email(email)
        user = self.model(email=email, name=name)

        user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email, name, password):
        """Creates and saves a new superuser with given details."""

        user = self.create_user(email, name, password)

        user.is_superuser = True
        user.is_staff = True

        user.save(using=self._db)

        return user

class User(AbstractBaseUser, PermissionsMixin):
    """Represents a "user" inside our system."""

    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        """Used to get a users full name."""

        return self.name

    def get_short_name(self):
        """Used to get a users short name."""

        return self.name

    def __str__(self):
        """Django uses this when it needs to convert the object to a string"""

        return self.email

Can anyone advise?


回答1:


The Problem is this:

django-rest-auth implements custom RegisterSerializer where the save method takes one additional positional argument request.

  def save(self, request):

This serializer is used by RegisterView from djang-rest-auth.

Normal serializer save method looks like this:

  def save(self, **kwargs):

You use your custom serializer in your view which parent is django-rest-auth RegisterView but your save method does not have the positional request argument, hence the problem.

And the logic in RegisterView assumes correct serializer implementation.

Try to use RegisterSerializer as parent to your serializer - you just need to investigate if it is straigtforward or you need to add/implement something else.

But it might be bit tricky.

But as it seems, you have custom model, custom serializer, custom view - i dont see any reason to use django-rest-auth RegisterView. Just implement your registration view.




回答2:


Because your custom registration view inherits from RegisterView,perform_create method define in RegisterView will call your serializer's save method with a request object based on the implementation and since your serializer inherits from ModelSerializer, the save method does not take any positional argument hence the error.

CustomUserSerializer needs to define a save method that takes the request object as an argument. Check this exempt below from django-rest-auth configuration

The custom REGISTER_SERIALIZER must define a def save(self, request) method that returns a user model instance.

I'll suggest you take a look at the implementation of the default REGISTER_SERIALIZER it'll guide how your custom serializer should look.



来源:https://stackoverflow.com/questions/51532288/django-rest-auth-error-save-takes-1-positional-argument-but-2-were-given

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!