I am trying to build a api for updating first and last name for my user. The api runs successfully but database is not updated which is the expected behavior
I have written the following API and trying to pass the patch request to it.
class UserSelfUpdateView(UpdateAPIView):
serializer_class = UserUpdateSerializer
permission_classes = [UserPermissions, ]
def update(self, request: Request, *args, **kwargs):
instance = User.objects.filter(id=self.request.user.id)
serializer = UserUpdateSerializer(instance, data=request.data,)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({'success': True}, status=status.HTTP_200_OK)
The serializer for the above request is:
class UserUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields: ('id', 'first_name', 'last_name')
The format in which I am trying to pass my request body is:
{
"first_name": "A",
"last_name": "B"
}
and this is how my model is defined:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=False)
last_name = models.CharField(_('last name'), max_length=30, blank=False)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
'''
Returns the first_name plus the last_name, with a space in between.
'''
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns the short name for the user.
'''
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
'''
Sends an email to this User.
'''
send_mail(subject, message, from_email, [self.email], **kwargs)
When running code with debug pointer results in the no database update but 200 status.
When running code without debug pointer results in 500 status code and following error message in response
AssertionError at /user/me-edit
("Creating a ModelSerializer without either the 'fields' attribute or the 'exclude' attribute has been deprecated since 3.3.0, and is now disallowed. Add an explicit fields = 'all' to the UserUpdateSerializer serializer.",)
Problem resides in the serializer, and concretely, inside this part of the code:
class Meta:
model = User
fields: ('id', 'first_name', 'last_name')
Fields are also a variable defined using =, so the code should look like:
class Meta:
model = User
fields = ('id', 'first_name', 'last_name')
That will help you on solving that AssertionError.
Related
When I send post request with data in profile model at that time this error show.
Error
{
"user_name": [
"Incorrect type. Expected pk value, received str."
] }
I saw this answer but don't know how to implement SlugRelatedField in serializers(OneToOneField)
models.py:
class CustomUser(AbstractUser):
# username_validator = UnicodeUsernameValidator()
username = models.CharField(
max_length=80,
unique=True,
)
email = models.EmailField(
unique=True,
blank=True,
)
.....
def __str__(self):
return '%s' %(self.username)
class Profile(models.Model):
user_name = models.OneToOneField(to = CustomUser,on_delete=models.CASCADE)
full_name = models.CharField(null=True,max_length=15, blank=True)
public_name = models.CharField(null=True,max_length=15, blank=True)
....
serializers.py:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['user_name','full_name','public_name']
views.py:
class ProfileApiview(CreateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
#Pradip - Have a look at this.
class ProfileSerializer(serializers.ModelSerializer):
user_name = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Profile
fields = ['user_name','full_name','public_name']
def create(self, validated_data):
user = self.context['request'].user
profile = Profile.objects.create(
user_name=user, full_name=validated_data['full_name'].............)
return profile
When I run api request I get a following error:
AttributeError: Got AttributeError when attempting to get a value for field email on serializer UserSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the tuple instance.
Original exception text was: 'tuple' object has no attribute 'email'.
New user gets inserted in database anyway, email field is filleld properly.
View:
class Register(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
return Response(serializer.data, status=status.HTTP_201_CREATED)
Serializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'name', 'password']
def create(self, validated_data):
user = User.objects.create_user(**validated_data),
return user
Model:
class User(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
username = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=60)
date_of_birth = models.DateField(blank=True, null=True)
bio = models.CharField(default='', max_length=10000)
photo = models.ImageField(max_length=255, null=True, blank=True)
email_verified_at = models.DateTimeField(null=True, blank=True)
email_token_time = models.DateTimeField(null=True, blank=True)
email_token = models.CharField(default='', max_length=64)
password_token_time = models.DateTimeField(null=True, blank=True)
password_token = models.CharField(default='', max_length=64)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
last_seen = models.DateTimeField(null=True, blank=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name']
objects = UserManager()
class Meta:
db_table = "User"
def __str__(self):
return self.username
I also have custom user manager, but that is probably irrelevant, and works as user does get inserted to database.
You have typo in this line:
user = User.objects.create_user(**validated_data),
It contains comma , in the last of line. So user become a tuple of user instance, not just user instance. It become (user,).
Should return user instance.
I know on this topic people asked a question before but my case is different and I have implemented almost all the solutions which I found but none of them are worked for me.
First I have defined three classes in models:
models.py
class User(AbstractBaseUser, PermissionsMixin):
""" User Model """
username = None
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
agency = models.ForeignKey('agency.Agency', on_delete=models.CASCADE, null=True)
weekly_email = models.NullBooleanField()
is_create_new_password = models.NullBooleanField(default=True)
is_active = models.BooleanField(default=True)
last_login_time = models.DateTimeField(null=True)
last_login_from = models.CharField(max_length=255, null=True)
created_at = models.DateField(default=timezone.now)
updated_at = models.DateField(default=timezone.now)
created_by = models.IntegerField(null=True)
updated_by = models.IntegerField(null=True)
""" The `USERNAME_FIELD` property tells us which field we will use to log in.
In this case, we want that to be the email field. """
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
""" Tells Django that the UserManager class defined above should manage
objects of this type. """
objects = UserManager()
class Role(models.Model):
""" Role Model """
name = models.CharField(max_length=255, unique=True)
class UserRole(models.Model):
""" User Role Model """
user = models.ForeignKey(User, on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
Then I have defined my serializer for user module:
serializers.py
class RegistrationSerializer(serializers.ModelSerializer):
""" Serializers registration requests and creates a new user. """
user_id = serializers.IntegerField(required=False)
email = serializers.EmailField(max_length=255)
name = serializers.CharField(max_length=255)
agency_id = serializers.IntegerField(source='agency.id', required=False)
role = serializers.CharField(source='role.name')
weekly_email = serializers.NullBooleanField()
last_login_time = serializers.DateTimeField(required=False)
last_login_from = serializers.CharField(max_length=255, required=False)
class Meta:
model = User
fields = (
'role', 'user_id', 'email', 'name', 'agency_id', 'weekly_email', 'last_login_time',
'last_login_from'
)
And At the end, I have defined my view file for user creation:
views.py
class UserCreateAPIView(APIView):
""" User create Api view class """
#Allow any user (authenticated or not) to hit this endpoint.
permission_classes = (IsAuthenticated,)
serializer_class = RegistrationSerializer
def post(self, request):
""" create user using following logic. """
request.data['user_id'] = request.user.id
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save(user=request.user)
return Response({'message': response['user']['created'], 'data': serializer.data},
status=status.HTTP_201_CREATED)
Now when I run it everything works fine like user is created, role is created as per my expectations. My view, serializer and models excuted but at the end on this line:
return Response({'message': response['user']['created'], 'data': serializer.data},
status=status.HTTP_201_CREATED)
I am facing error like,
AttributeError: Got AttributeError when attempting to get a value for field `role` on serializer `RegistrationSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'role'.
I think you need to use ModelSerializer
class RegistrationSerializer(serializers.Serializer):
to
class RegistrationSerializer(serializers.ModelSerializer):
I'm trying to implement a Twitter-like follow system (one user can follow and be followed by many other users). I've tried a number of ways, but I keep getting errors. Currently, every time I drop debuggers or print statements throughout the form, I find that I don't ever get into the clean methods, nor is kwargs ever populated with values.
I want to be able to pass in the follower & following as arguments to the Form and just assign them in the __init__ but everything is going wrong. When I get the response back in Javascript (React & Redux), all I'm getting is errors for both follower & following saying "This field is required."
Here's what I've got so far:
Models
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=100, unique=True)
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Meta:
verbose_name = 'user'
verbose_name_plural = 'users'
class UserFollow(models.Model):
follower = models.ForeignKey('User', models.CASCADE, related_name='follows')
following = models.ForeignKey('User', models.CASCADE, related_name='followed_by')
class Meta:
unique_together = ('follower', 'following')
def to_user(self):
return {
'id': self.pk,
'follower': self.follower.pk,
'following': self.following.pk
}
Views
def follow(request, id):
following = User.objects.get(pk=id)
form = UserFollowForm(follower=request.user, following=following)
if form.is_valid():
user_follow = form.save()
return JsonResponse({'user_followed': following.to_user()})
return JsonResponse({'error': form.errors}, status=400)
Forms
class UserFollowForm(forms.ModelForm):
follower = forms.CharField()
following = forms.CharField()
class Meta:
model = UserFollow
fields = ('follower', 'following')
def __init__(self, *args, **kwargs):
self.follower = kwargs.pop('follower', None)
self.following = kwargs.pop('following', None)
super(UserFollowForm, self).__init__(*args, **kwargs)
def clean_follower(self):
return self.follower
def clean_following(self):
return self.following
You haven't passed any data into the form, so it is not bound and will never be validated.
However I don't understand why you want to use a form here at all. You don't seem to want to take posted data from the user, and there is no validation to be done. Just create your UserFollow instance directly.
def follow(request, id):
following = User.objects.get(pk=id)
user_follow = UserFollow.objects.create(follower=request.user, following=following)
return JsonResponse({'user_followed': user_follow.to_user()})
I have this user serializer:
class SimpleUser(models.Model):
class meta:
abstract = True
email = models.EmailField(_('email address'), blank=False)
password = models.CharField(_('password'), max_length=128)
first_name = models.EmailField(_('first name'), blank=True)
class UserSerializer(ModelSerializer):
class Meta:
model = SimpleUser
And this is my view:
class UserView(APIView):
def patch(self, request, user_id):
firstname = request.data.get('first_name', '')
email = request.data.get('email', '')
password = request.data.get('password', '')
user = User.objects.get(id=user_id)
serializer = UserSerializer(instance=user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_400_BAD_REQUEST)
I send this json request, but only the password and email are updated and first_name not updated.
{
"password":"6524266",
"email":"HH#bb.com",
"first name":"dsfxvxc"
}
I get the status 200 OK and can get the saved object in serializer.save()
What is wrong with my code?
You set firstname as emailfield
first_name = models.EmailField(_('first name'), blank=True)
Changes this to CharField or related fields, something like this,
first_name = models.CharField(max_length=30)