fixed error instance object is not callable - python

I need code for editing user details like first_name , last_name by using APIView Class based. THe serializers.py and views.py are given under but it is not making the changes according to the user details . i am passing token for user authentication. Any assistance will be appreciated.
Serializers.py
class UserEditSerializer(serializers.Serializer):
email = serializers.EmailField(required=True)
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
def update(self, validated_data, instance):
instance.first_name = validated_data.get('first_name')
instance.email = validated_data.get('email')
instance.last_name = validated_data.get('last_name')
instance.save()
return instance
Views.py
class UserEditProfile(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def get_object(self):
return self.request.user
def post(self, request):
self.object = self.get_object()
serializer = UserEditSerializer(data=request.data)
if serializer.is_valid():
self.object.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

How would the serializer know it must update a user if you don't provide it ?
serializer = UserEditSerializer(data=request.data)
should be:
serializer = UserEditSerializer(self.object, data=request.data)
Edit:
Also, remove the () after return instance

This view will work . Thanks Linovia
class UserEditProfile(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def post(self, request):
obj = User.objects.get(id=request.user.id)
serializer = UserEditSerializer(obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Related

how do you automatically fill this field (bizuser)ForeignKey rather than having to look for bizuser ID

MY model
class XP(models.Model):
bizuser = models.ForeignKey(BizUser, on_delete=models.CASCADE)
current_xp_price = models.IntegerField(default=0)
xp_created_at = models.DateTimeField(auto_now_add=True)
xp_updated_at = models.DateTimeField(auto_now_add=True)
i have this function that creates an XP i want if the current user is authenticated(jwttokens) the user can then go ahead to create the XP .when i go to post this data i get to fields that i have to fill that is current_xp_price and bizuser which is a ForeignKey
Views
class create_xp(APIView):
def post(self, request):
if request.user.is_authenticated:
current_user = request.BizUser
serializer = XPSerializer(data=request.data)
request.data["bizuser"] = current_user.id
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)
else:
return Response(status=status.HTTP_401_UNAUTHORIZED)
serializers
class XPSerializer(serializers.ModelSerializer):
class Meta:
model = XP
fields = ['current_xp_price', ]

DRF ViewSet operation authorization with rules

Considering the following model
class MyUser(AbstractBaseUser):
ADMIN = 0
TEACHER = 100
STUDENT = 200
UNSPECIFIED = 256
USER_TYPE_CHOICES = (
(ADMIN, 'admin'),
(TEACHER, 'teacher'),
(STUDENT, 'student'),
(UNSPECIFIED, 'unspecified')
)
...
user_type = models.IntegerField(db_column='userType', choices=USER_TYPE_CHOICES, blank=True, default=UNSPECIFIED)
And the following ViewSet
class CourseViewSet(ViewSet):
def create(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
Using django-rules, how can the create() operation in CourseViewSet be restricted to only users of user_type TEACHER?
If you want to auto apply permissions defined in your model you can use
in your course model something like this
from rules import predicates
#predicates.predicate()
def check_teacher(user):
if not hasattr(user, 'user_type'):
return False
if user.user_type == 'teacher':
return True
return False
class Course(models.Model):
....
class Meta:
rules_permissions = {
"add": check_teacher,
"read": rules.always_allow,
}
and your view
from rules.contrib.rest_framework import AutoPermissionViewSetMixin
class CourseViewSet(AutoPermissionViewSetMixin, viewsets.ViewSet):
def get_queryset(self):
return Course.objects.all()
def create(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)

How to Patch an User Model of Django with Django RF?

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)

Django RestFrame work to update the fied

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"

'dict' object has no attribute 'save' POST doesn't work

I'm building a REST web service, the GET method seems to be working all right
but when it comes to POST error message always shows up:
'dict' object has no attribute 'save'
models.py
from django.db import models
class Users(models.Model):
Fullname = models.CharField(max_length=50)
Username = models.CharField(max_length=15)
Password = models.CharField(max_length=8)
Email = models.CharField(max_length=50, unique=True)
Type = models.CharField(max_length=5)
TwitterName = models.CharField(max_length=15, unique=True)
FacebookName = models.CharField(max_length=15, unique=True)
CreationDate = models.DateTimeField()
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('Fullname', 'Username', 'Email', 'Password', 'Type', 'TwitterName', 'FacebookName')
views.py
#api_view(['GET', 'POST'])
def users_list(request, format=None):
if request.method == 'GET':
users = Users.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UserSerializer(request.DATA, many=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
I'm using PyCharm and Django 1.7
If you want to save the POST data then you should pass the data to data keyword argument:
serializer = UserSerializer(data=request.DATA, many=True)
if serializer.is_valid():
...
Also I would suggest you to use Class based views with Mixins as that will make your code much cleaner and shorter:
from rest_framework import generics, mixins
class UserList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Users.objects.all()
serializer_class = UserSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

Categories

Resources