This is my serializers.py:
from rest_framework import serializers
from django.contrib.auth.models import User
from CMSApp.mixins import SetCustomErrorMessagesMixin
from django.utils.translation import gettext as _
from rest_framework.validators import UniqueValidator
from django.core.validators import RegexValidator
class UserSerializer(SetCustomErrorMessagesMixin, serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email')
custom_error_messages_for_validators = {
'username': {
UniqueValidator: _('This username is already taken. Please, try again'),
RegexValidator: _('Invalid username')
}
}
def create(self, validated_data):
user = User.objects.create_user(
email = validated_data['email'],
username = validated_data['username'],
password = validated_data['password'],
)
return user
and this is my mixins.py:
class SetCustomErrorMessagesMixin:
"""
Replaces built-in validator messages with messages, defined in Meta class.
This mixin should be inherited before the actual Serializer class in order to call __init__ method.
Example of Meta class:
>>> class Meta:
>>> model = User
>>> fields = ('url', 'username', 'email', 'groups')
>>> custom_error_messages_for_validators = {
>>> 'username': {
>>> UniqueValidator: _('This username is already taken. Please, try again'),
>>> RegexValidator: _('Invalid username')
>>> }
>>> }
"""
def __init__(self, *args, **kwargs):
# noinspection PyArgumentList
super(SetCustomErrorMessagesMixin, self).__init__(*args, **kwargs)
self.replace_validators_messages()
def replace_validators_messages(self):
for field_name, validators_lookup in self.custom_error_messages_for_validators.items():
# noinspection PyUnresolvedReferences
for validator in self.fields[field_name].validators:
if type(validator) in validators_lookup:
validator.message = validators_lookup[type(validator)]
@property
def custom_error_messages_for_validators(self):
meta = getattr(self, 'Meta', None)
return getattr(meta, 'custom_error_messages_for_validators', {})
When I go to the URL /users/1, this is the view which is called:
class user_detail(APIView):
"""
Get, update or delete a specific user.
"""
def get_object(self, pk):
try:
return User.objects.get(pk=pk)
except User.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
def get(self, request, pk):
user = self.get_object(pk)
serializer = UserSerializer(user)
return Response(serializer.data)
def put(self, request, pk):
user = self.get_object(pk)
serializer = UserSerializer(user, data=request.DATA)
if serialzier.is_valid():
serializier.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
user = self.get_object(pk)
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
The issue is, when I go to the URL /users/1, Django returns an attribute error, saying:
AttributeError at /CMS/users/1
Got AttributeError when attempting to get a value for field `username` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Response` instance.
Original exception text was: 'Response' object has no attribute 'username'.
I checked my UserSerializer and I did specify correctly that
fields = ('username', 'password', 'email')
so I can't seem to find the issue. Any idea why Django is giving an error saying that "The serializer field might be named incorrectly and not match any attribute or key on the Response
instance." even though 'username' is named correctly?
The issue is in your
get_object
method, you're returning a 404 response instead of raising aHttp404
exception. Because of that, theResponse
is being passed into your serializer, and clearly theResponse
does not have ausername
field.The last part of your stack trace said
Which was the signal: there is only one place where you are returning a
Response
back to a serializer.