Perform Create Always Fails Django REST Framework - django

I'm trying to add a custom create method, and am using the Django REST FRAMEWORK. Once a user is created, I want to create an auth token and then return a JSON response with this user AND an auth token.
UPDATE: I was able to update the below to create the user, but now I am getting Cannot assign "<User: User object>": "Token.user" must be a "User" instance What am i doing wrong?
How can I modify the below so when POST to users/, I create a user, create an auth token, and return both?
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 's3_link', 'phone_confirmed', 'agreed_to_tos', 'phone_number', 'facebook_id', 'stripe_id', 'phone_verification_code')
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
##ISSUE WITH CODE STARTS HERE
user = serializer.save()
token = Token.objects.create(user=user)

You could use a custom Response to add the token to the user data:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 's3_link', 'phone_confirmed', 'agreed_to_tos', 'phone_number', 'facebook_id', 'stripe_id', 'phone_verification_code')
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Customized rest_framework.mixins.CreateModelMixin.create():
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# Your code
user = serializer.save()
token = Token.objects.create(user=user)
# Create custom response
data = serializer.data
# You may need to serialize your token:
# token = token.your_token_string_field
data.update({'token': token})
headers = self.get_success_headers(serializer.data)
return Response(data, status=status.HTTP_201_CREATED, headers=headers)

If you want to create a user, I would recommend following this format:
serializers.py:
class AccountCreateSerializer(serializers.ModelSerializer):
class Meta:
model = User
# You will need to check accuracy of fields, but this is for demo purposes
fields = ['username', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User(
username=validated_data['username'],
email=validated_data['email']
)
user.set_password(validated_data['password'])
user.save()
return user
views.py:
from rest_framework import generics
from serializers.py import AccountCreateSerializer
class AccountCreateAPIView(generics.CreateAPIView):
serializer_class = AccountCreateSerializer

Related

How to use 2 models within a serializer in Django REST API?

I just started using the Django Rest Framework recently and was wondering how to use 2 models within a single serializer. I have a custom model named 'Profile' and am also using a default Django model 'User'. With these two tables, I planned to use nested representations. Finally, in order to test the RegisterAPI, I wanted to create data using the POSTMAN tool but currently, it's not working as expected.
This is what I had done so far:
models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
company = models.CharField(max_length=100, blank=True, null=True)
address = models.TextField()
views.py:
class RegisterAPI(APIView):
permission_classes = [AllowAny]
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
content = {
'result': 'Thanks for registering!'
}
return Response(content, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py:
from rest_framework import serializers
from myapp.models import Profile
from django.contrib.auth.models import User
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['company', 'address']
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(many = True)
class Meta:
model = User
fields = ['username', 'email', 'password', 'profile']
def create(self, validated_data):
profile_data = validated_data.pop('profile')
password = validated_data.pop('password', None)
# instance = self.Meta.model(**validated_data)
user = User.objects.create(**validated_data)
if password is not None:
user.set_password(password)
user.save()
Profile.objects.create(user = user, **profile_data)
return user
Within POSTMAN, I am not able to set the fields 'company' and 'address' for the Profile serializer. How can I do this?

Getting { "user": [ "This field is required."] } on Postman everttime I try to post

I am trying to create a sign up api using createAPIView on Django rest Framework. Everytime I post data on Postman it returns the above error although it gets response when I run it in browser. Also the image field is causing problem in raw data on postman. I have tried a lot of things but nothng has seemed to work. What am I supposed to do?
serializers
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
password = serializers.CharField(min_length=8)
class Meta:
model = User
fields = ('id', 'first_name','last_name', 'email', 'username','password')
extra_kwargs = {'user': {'required': False}}
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
code = serializers.CharField(read_only=True)
avatar = serializers.FileField(use_url=False)
class Meta:
model = UserProfile
fields = '__all__'
extra_kwargs = {'user': {'required': False}}
def create(self, validated_data):
user_data = validated_data.pop('user',None)
image = validated_data.pop('avatar')
upr=UserProfile.objects.create(user=user_data, image=image**validated_data)
return upr
views
class UserCreate(generics.ListCreateAPIView):
serializer_class = UserProfileSerializer
user_serializer = UserSerializer
queryset = UserProfile.objects.all()
parser_classes = (FormParser,MultiPartParser,FileUploadParser)
def post(self, request):
serializer = UserProfileSerializer(data=request.data)
print(request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
You are trying to send profile data without creating a user first. And a profile object must be applied to an already existing user.

POST http://127.0.0.1:8000/api/register/ 400 (Unauthorized)

view.py
class UserViewSet(viewsets.ModelViewSet):
""" API endpoint that allows users to be viewed or edited. """
serializer_class = UserSerializer
queryset = UserRegister.objects.all()
authentication_classes = (TokenAuthentication,)
permission_classes = (permissions.UpdateRegister,)
This is the view.py file. Here i have added authentication and permission to my view set.
permission.py
class UpdateRegister(permissions.BasePermission):
""" Allow user to edit their own profile. """
def has_object_permissions(self, request, view, obj):
""" Check user is trying to edit their own profile. """
if request.method in permissions.SAFE_METHODS:
return True
return obj.id == request.user.id
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserRegister
fields = ('id', 'name', 'email', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
""" Create and return a new user"""
user = UserRegister(
email=validated_data['email'],
name=validated_data['name'],
)
user.set_password(validated_data['password'])
user.save()
return user
Error shown in network tab
So guy i am being bother by this error. Hope you guys will address my mistake and help me to solve the error.

Creating user with default group django rest framework viewsets

how do I create user with default group? my serializer
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password')
def create(self, validated_data):
user = super(UserSerializer, self).create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
views.py
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
How do I set user group when creating from this view?
Just add something like
user.groups.add(Group.objects.get(name='Whatever'))
after user.save() in the create method.

Django Rest Framework - return auth token after registration

I want to return an auth token in json after successful user registration. How can I do this ?
For registration I use the following
seriazilers.py
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = [
'id',
'username',
'password',
'email',
]
write_only_fields = ('password',)
read_only_fields = ('id',)
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
)
user.set_password(validated_data['password'])
user.save()
return user
views.py
class CreateUser(CreateAPIView):
queryset = Profile.objects.all()
serializer_class = UserSerializer
The are many ways to do this. Here is example in context of your existing code. (put this in your views.py)
from rest_framework.response import Response
from rest_framework.authtoken.models import Token
from rest_framework import status
class CreateUser(CreateAPIView):
queryset = Profile.objects.all()
serializer_class = UserSerializer
def create(self, request, *args, **kwargs): # <- here i forgot self
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
token, created = Token.objects.get_or_create(user=serializer.instance)
return Response({'token': token.key}, status=status.HTTP_201_CREATED, headers=headers)
Here's a simple solution for the user when he/she wants to login/sign-in
first of all download django-rest-framework-jwt with pip
pip install djangorestframework-jwt
in your UserSerializer add this to make sure the username and password are correct (add as many fields as you wish)
username = serializers.CharField(read_only=True)
password = serializers.CharField(read_only=True)
Now in your view.py add this
# authenticate: will check if the user exist
from django.contrib.auth import authenticate
# api_settings: will help generating the token
from rest_framework_jwt.settings import api_settings
def login_page(request):
payload_handler = api_settings.JWT_PAYLOAD_HANDLER
encode_handler = api_settings.JWT_ENCODE_HANDLER
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = authenticate(username=request.data['username'], password=request.data['password'])
if user:
payload = payload_handler(user)
token = encode_handler(payload)
return Response({'token': token})
And mainly that's it! hope it helps!