0

I'm using Django 1.9 and DRF 3.0, here is my view:

class UserList(generics.ListCreateAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAuthenticatedOrCreate,)

    def create(request, *args, **kwargs):
        user = MyUser.objects.create(
            user_name=request['user_name'],
            email=request['email'],
        )
        user.set_password(request['password'])
        user.save()
        login(request, user)
        return user

and my serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyUser
        fields = ("id", "email", "user_name", "password", "user_avatar", "user_gender", "user_point", "user_details", "user_register_time")
        write_only_fields = ("password",)
        read_only_fields = ("id", "user_avatar", "user_gender", "user_point", "user_details", "user_register_time")

and Traceback:

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.4/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.4/site-packages/rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/rest_framework/generics.py", line 246, in post
    return self.create(request, *args, **kwargs)
  File "/Users/windson/uni/srv/unicooo/www/api/views.py", line 105, in create
    user_name=request['user_name'],
TypeError: 'UserList' object is not subscriptable

And my perious version is like this:

class UserList(generics.ListCreateAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAuthenticatedOrCreate,)

and my serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyUser
        fields = ("id", "email", "user_name", "password", "user_avatar", "user_gender", "user_point", "user_details", "user_register_time")
        write_only_fields = ("password",)
        read_only_fields = ("id", "user_avatar", "user_gender", "user_point", "user_details", "user_register_time")

    def create(request, *args, **kwargs):
        user = MyUser.objects.create(
            user_name=request['user_name'],
            email=request['email'],
        )
        user.set_password(request['password'])
        user.save()
        return user

I want to login user after they sign up, so I rewrite the create method and using login() method, and the error message is "'UserList' object is not subscriptable", how to fix it? Thanks.

Windsooon
  • 6,864
  • 4
  • 31
  • 50

2 Answers2

1

I think the problem is that you are returning a user object directly, I think it should be as follows:

 from rest_framework import status
 class UserList(generics.ListCreateAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAuthenticatedOrCreate,)

    def create(request, *args, **kwargs):
        user = MyUser.objects.create(
            user_name=request.POST.get('user_name'),
            email=request.POST.get('email'),
        )
        user.set_password(request.POST.get('password'))
        user.save()
        user = authenticate(user_name=request.POST.get('user_name'), password=request.POST.get('password'))
        login(request, user)
        serializer = UserSerializer(user)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

Update I've updated the code above regarding this from the documentation.

Calling authenticate() first

When you’re manually logging a user in, you must successfully authenticate the user with authenticate() before you call login(). authenticate() sets an attribute on the User noting which authentication backend successfully authenticated that user (see the backends documentation for details), and this information is needed later during the login process. An error will be raised if you try to login a user object retrieved from the database directly. https://docs.djangoproject.com/en/1.9/topics/auth/default/#how-to-log-a-user-in

Ahmed Hosny
  • 1,162
  • 10
  • 21
  • Still not working, TypeError: 'UserList' object is not subscriptable – Windsooon Feb 16 '16 at 08:17
  • check the updates and if the error changes, please show the traceback. Updated again – Ahmed Hosny Feb 16 '16 at 08:41
  • No tradeback this time, I can create user now but when I redirect to another page, still not authentication, I post username, password, email using ajax. and I just get them back in my http response without response cookies. – Windsooon Feb 16 '16 at 08:57
  • I've updated my answer again. But what do you mean by > response cookies – Ahmed Hosny Feb 16 '16 at 09:27
  • not working, and the password save to the database become decrypt. – Windsooon Feb 16 '16 at 09:46
  • You mean encrypted, yes this make sense. As long as it returned 201 so it login successfully. Make sure you are using `django.contrib.auth.middleware.AuthenticationMiddleware` in `MIDDLEWARE_CLASSES` inside settings.py or similar middleware. So what is wrong now exactly? you can change serializer.data and return anything else if you want. – Ahmed Hosny Feb 16 '16 at 09:54
  • Forgive my poor english, I'd change the code to what I used to write. I follow Maxim Dunaevsky in this question http://stackoverflow.com/questions/16857450/how-to-register-users-in-django-rest-framework. It work fine and the password is encrypted, but when I change my code like yours, the password become not encrypted, and the user still not auth.I'm using session auth in django, and I think login() method should create cookies and session for user automatic. It returned 201 so create successfully but haven't login yet. – Windsooon Feb 16 '16 at 10:19
  • do you set AUTH_USER_MODEL = 'yourapp.MyUser' in settings.py? as the only difference I can figure is that it uses `get_user_model` which is preferably should be used – Ahmed Hosny Feb 16 '16 at 12:30
0

This finally work:

class UserList(generics.ListCreateAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAuthenticatedOrCreate,)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        new_user = authenticate(email=request.POST.get('email'),
            password=request.POST.get('password'),
            )
        if new_user is not None:
            if new_user.is_active:
                django_login(request, new_user)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Windsooon
  • 6,864
  • 4
  • 31
  • 50
  • what does your urls.py look like? what does the serializer look like? and finally what does the registration request body look like? – Fed May 20 '21 at 16:04