I have a profile model for user to update. I want to have a rest api for that. I have a profile model which is too big than usual. I am working to update the user profile but I am having confusion on which serializer should i use to update the profile. Here is what i have done till now
I created the serializer for user and user profile.
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'user','current_location', 'permanent_location', 'dob',
'about_me', 'gender_status', 'create_profile_for', 'marital_status',
'height', 'weight', 'body_type', 'complexion',)
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=True)
class Meta:
model = User
fields = ('id', 'profile', 'username', 'email', 'first_name', 'last_name',)
def update(self, instance, validated_data):
# instance = super(UserSerializer, self).update(validated_data)
profile_data = validated_data.pop('profile')
#updating user data
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.email = validated_data.get('first_name', instance.email)
#updating profile data
if not instance.profile:
Profile.objects.create(user=instance, **profile_data)
instance.profile.current_location = profile_data.get('current_location', instance.profile.current_location)
instance.profile.permanent_location = profile_data.get('permanent_location', instance.profile.permanent_location)
instance.profile.weight = profile_data.get('weight', instance.profile.weight)
instance.profile.height = profile_data.get('height', instance.profile.height)
instance.profile.about_me = profile_data.get('about_me', instance.profile.about_me)
instance.profile.create_profile_for = profile_data.get('create_profile_for', instance.profile.create_profile_for)
instance.profile.body_type = profile_data.get('body_type', instance.profile.body_type)
instance.save()
return instance
This is my view
class UserProfile(APIView):
serializer_class = UserSerializer
def get(self, request, token=None, format=None):
"""
Returns a list of profile of user
"""
reply={}
try:
profile_instance = Profile.objects.filter(user=self.request.user)
if token:
profile = profile_instance.get(token=token)
reply['data'] = self.serializer_class(profile).data
else:
reply['data'] = self.serializer_class(profile_instance, many=True).data
except:
reply['data']=[]
return Response(reply, status.HTTP_200_OK)
def post(self, request, token=None, format=None):
"""
update a profile
"""
profile=None
if not token is None:
try:
profile = Profile.objects.get(user=request.user, token=token)
except Profile.DoesNotExist:
return error.RequestedResourceNotFound().as_response()
except:
return error.UnknownError().as_response()
serialized_data = self.serializer_class(profile, data=request.data, partial=True)
reply={}
if not serialized_data.is_valid():
return error.ValidationError(serialized_data.errors).as_response()
else:
profile = serialized_data.save(user=request.user)
reply['data']=self.serializer_class(profile, many=False).data
return Response(reply, status.HTTP_200_OK)
How should i handle my user profile update?
Updated my UserSerializer with update function
UPDATE with Dean Christian Armada solution
class UserProfile(APIView):
serializer_class = ProfileSerializer
def get(self, request, token=None, format=None):
"""
Returns a list of profile of user
"""
reply={}
try:
profile_instance = Profile.objects.filter(user=self.request.user)
if token:
profile = profile_instance.get(token=token)
reply['data'] = self.serializer_class(profile).data
else:
reply['data'] = self.serializer_class(profile_instance, many=True).data
except:
reply['data']=[]
return Response(reply, status.HTTP_200_OK)
def put(self, request, token=None, *args, **kwargs):
"""
update a profile
"""
print('token', token)
if token:
try:
profile = Profile.objects.get(token=token)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
serialized_data = self.serializer_class(profile, data=request.data)
reply={}
if serialized_data.is_valid():
profile = serialized_data.save(user=request.user)
reply['data'] = self.serializer_class(profile, many=False).data
return Response(reply, status.HTTP_200_OK)
else:
return Response(serialized_data.errors, status.HTTP_400_BAD_REQUEST)
With your code, i get This QueryDict instance is immutable error
It's a standard to use the
PUT
request method for updating in your current code and situation it is better to use theProfileSerializer
since it has more fields. Also, the way I see it you only have three fields in the User object that can be changed and those three fields I assume is rarely changed.views.py
serializers.py
Simply just set the user to read only for it to avoid validation