I'm new in Django and DRF and I'm trying to create a new user through POST request. I send the username and password parameters but django doesn't identify the parameters inside the POST request.
My serializer:
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user=get_user_model().objects.create(
username = validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
class Meta:
model = get_user_model()
fields = ('username', 'password')
My view class:
class CreateUserView(CreateAPIView):
model = get_user_model()
permission_classes = (AllowAny,)
serializer_class = UserSerializer
I have tried to use serializers.ModelSerializer and serializer.Serializers but don't have success.
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = UserModel.objects.create_user(**validated_data)
return user
class Meta:
model = YOUR_MODEL
fields = ('username', 'password',)
class CreateUserView(CreateAPIView):
model = YOUR_MODEL.objects.all()
permission_classes = (AllowAny,)
serializer_class = UserSerializer
You can do View as this and check your errors.
view.py
class CreateUser(APIView):
permission_classes = (AllowAny,)
def post(self, request):
post_data = request.data
print post_data # See what is your post DATA
serializer = UserSerializer(data=post_data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data={'user':serializer.data})
return Response(data={'user':serializer.errors})
Related
I'm trying to set endpoints to PATCH or DELETE users according to a permission but my current code only allows me to apply those changes to the account I'm logged to. Is there a way for me to pass an id or an email as an argument in the body of a request to modify other accounts without using the ID in the URL? Thank you.
serializers.py
class UserModifySerializer(serializers.ModelSerializer):
class Meta:
model = User
exclude = ['id', 'user_role']
class UserSerializer(serializers.ModelSerializer):
organization = OrganizationSerializer(read_only=True)
class Meta:
model = User
fields = ['id', 'email', 'first_name', 'last_name', 'organization', 'user_role', 'language']
models.py
class UserViewSet(mixins.UpdateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
swagger_schema = None
serializer_class = UserSerializer
#action(detail=False, methods=['patch'], permission_classes = [IsAuthenticated], url_path='modify-user')
def update_user(self, request):
user = User.objects.get(id=self.request.user.id)
if user.user_role in [Roles.ORGANIZATION_USER, Roles.ORGANIZATION_ADMIN, Roles.WEBSITE_ADMIN]:
serializer = UserModifySerializer(user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save(**serializer.validated_data)
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_401_UNAUTHORIZED)
#action(detail=False, methods=['delete'], permission_classes = [IsWebsiteAdmin, IsOrganizationAdmin])
def delete_member(self, request):
user = User.objects.get(id=self.request.user.id)
if user.user_role in [Roles.ORGANIZATION_ADMIN, Roles.WEBSITE_ADMIN]:
members = User.objects.filter(organization=self.request.user.organization)\
.filter(id=id).delete()
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_401_UNAUTHORIZED)
You can put the necessary data in a json format inside request's body and then access it in the view like so:
data = json.loads(request.body)
How you put the data depends on how you call the view.
I was trying to register user in django using User model from 'django.contrib.auth.models', but when encrypting password, it shows 'The crypt module is not supported on Windows'. Also I tried importing from passlib.hash the pbkdf2_sha256 to encrypt the data.
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
encryptedpass = pbkdf2_sha256.encrypt(validated_data['password'], rounds=12000, salt_size=32)
user = User.objects.create_user(username=validated_data['username'], email=validated_data['email'], password=encryptedpass)
return user
views.py
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
class LoginAPI(KnoxLoginView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format=None):
encryptedpass = pbkdf2_sha256.encrypt(request.data['password'], rounds=12000, salt_size=32)
mydata = {'username':request.data['username'], 'password':encryptedpass}
serializer = AuthTokenSerializer(data=mydata)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return super(LoginAPI, self).post(request, format=None)
# Get User API
class UserAPI(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated,]
serializer_class = UserSerializer
def get_object(self):
return self.request.user
But during authentication in login part, it does not match the credentials, maybe because the function checking for validity uses some other encryption method. How to solve this issue.
I have UserProfile model that contains phone, profile_photo and some fields of Django default User model like first_name, last_name, email and I am trying to update some of these fields.
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, verbose_name="User")
phone = models.CharField(max_length=16, verbose_name="Phone")
profile_photo = models.ImageField(null=True, blank=True, upload_to=user_directory_path, verbose_name="Profile Photo")
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'first_name', 'last_name', 'email')
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(partial=True)
class Meta:
model = UserProfile
fields = '__all__'
def create(self, validated_data):
user_profile = UserProfile.objects.create(**validated_data)
return user_profile
views.py
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
authentication_classes = (TokenAuthentication,)
#detail_route(methods=['PATCH'], url_path='update-partial')
def user_profile_update_partial(self, request, pk=None):
profile = UserProfile.objects.get(id=pk)
serializer = self.get_serializer(profile, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
If I send profile_photo, phone, first_name or last_name data with this #detail_route I am only able to update phone and profile_photo fields. Also getting Bad Request error when profile_photo data not sending.
How can I implement the partial_update with PATCH method?
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
authentication_classes = (TokenAuthentication,)
def partial_update(self, request, *args, **kwargs):
profile = self.get_object()
serializer = self.get_serializer(profile, data=request.data, partial=True)
if serializer.is_valid():
user_serializer = UserSerializer(profile.user, data=request.data, partial=True)
if user_serializer.is_valid():
user_serializer.save()
serializer.save()
return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
else:
return Response(data=user_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(data=serializer.errors,status=status.HTTP_400_BAD_REQUEST)
Q1:How to implement PATCH method?
A1:Override partial_update method.
Q2:How to update first_name or last_name?
A2:Update it with another Serializer named UserSerializer.(If you want update password,you need use make_password method to create encoded password before save raw password to database)
I copied https://pypi.python.org/pypi/fh-drf-friendship/0.1.1 (Because i don't know how to apply fh-drf-friendship on my project.)
views.py
class FriendViewSet(NestedViewSetMixin, mixins.ListModelMixin, mixins.CreateModelMixin,
mixins.DestroyModelMixin, viewsets.GenericViewSet):
serializer_class = UserSerializer
def create(self, request, *args, **kwargs):
request.data['to_user'] = self.get_parents_query_dict()['user']
serializer = FriendSerializer(data=request.data)
if serializer.is_valid():
instance = serializer.save()
headers = self.get_success_headers(serializer.data)
serializer = FriendReadSerializer(instance)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get_object(self):
to_user = User.objects.get(pk=self.get_parents_query_dict().get('user'))
from_user = User.objects.get(pk=self.kwargs.get('pk'))
return Friend.objects.get(to_user=to_user, from_user=from_user)
serializers.py
class UserSerializer(serializers.ModelSerializer):
related_postwriter = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
related_commentwriter = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'email', 'related_postwriter', 'related_commentwriter')
class FriendSerializer(rest_framework_common.serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(source='from_user', queryset=User.objects.all())
class Meta:
model = Friend
exclude = ('url', 'from_user',)
def create(self, validated_data):
fr = FriendshipRequest.objects.get(from_user=validated_data['from_user'], to_user=validated_data['to_user'])
if fr and fr.accept():
return Friend.objects.get(from_user=validated_data['from_user'], to_user=validated_data['to_user'])
class FriendReadSerializer(rest_framework_common.serializers.ModelSerializer):
user = UserSerializer(source='from_user')
created_at = serializers.DateTimeField(source='created')
class Meta:
model = Friend
exclude = ('url', 'from_user', 'to_user', 'created',)
django version == 1.9.7
django rest framework version == 3.4.1
python3 == 3.5
On urls.py, there are router.register(r'friend', views.FriendViewSet, base_name='friend')
And when i go http://127.0.0.1:8000/friend/ on web browser,
DoesNotExist at /friend/
User matching query does not exist. comes.
How can i solve it?
My serializer fun is
class change_pwdform(serializers.ModelSerializer):
def update(self, instance, validated_data):
user.set_password(validated_data.get('new_password', new_password))
user.save()
return instance
old_password = serializers.CharField( style={'input_type': 'password'})
new_password = serializers.CharField( style={'input_type': 'password'})
class Meta:
fields = ( 'pty_email','old_password','new_password',)
model = registration
in my model i have only the filed called
password field in model
my view function to change password is,
class Change_Password(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
serializer_class = change_pwdform
def post(self, request, format=None):
email = request.data['pty_email']
pwd = request.data['old_password']
user = registration.objects.filter(pty_email=email, pty_password=pwd)
if user:
user = registration.objects.get(pty_email=email)
request['password'] = request.data['new_password']
print request.data //says quickdict of email , password , new_password, and old_password
serializer = change_pwdform(object, data=request.DATA, partial=True)
if serializer.is_valid():
serializer.save()
data = { "result":"success"}
return Response(data)
error ={"Invalid"}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
This request return a dict ack: success but the password is not yet changed.
Thanks in advance..
You can wright an update function in your serializers like this.Following
def update(self, instance, validated_data):
user.set_password(validated_data.get('new_password', new_password))
user.save()
return instance
Here user is the user object and in your views.py you have to pass the model object like this
change_pwdform = change_pwdform(object, data=request.DATA, partial=True)
This worked for me and you can also refer "http://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-update"