Abhishek Surela
Abhishek Surela

Reputation: 3

'AttributeError: 'User' object has no attribute 'phone'' in Django Rest Framework

I understand that the default user model does not have a field named 'phone'. However, I am trying to retrieve all the registered users from the default user model, along with additional fields such as 'phone', 'phone_verified', 'email_verified', 'phone_code', and 'email_code' from a custom UserProfile model which inherits from the default user model using a OneToOneField. To achieve this, I have created a UserSerializer which serializes the default User model, and a nested UserProfileSerializer that utilizes the UserSerializer class and the UserProfile model. My goal is to have the nested UserProfileSerializer serialize data from both the user model and the custom UserProfile model. Unfortunately, I am encountering the following error: AttributeError at /register/ - Got AttributeError when attempting to get a value for field 'user' on serializer 'UserProfileSerializer'. The serializer field might be named incorrectly and not match any attribute or key on the 'User' instance. The original exception text was: 'User' object has no attribute 'user'.

models.py:

from django.db import models
from django.contrib.auth.models import User


# Create your models here.

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone = models.CharField(max_length=20)
    phone_verified = models.BooleanField(default=False)
    email_verified = models.BooleanField(default=False)
    phone_code = models.CharField(max_length=10)
    email_code = models.CharField(max_length=10)

serializer.py:

from django.core import validators
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import UserProfile
from datetime import datetime


class UserSerializer(serializers.ModelSerializer):
    first_name = serializers.CharField(required=True)
    last_name = serializers.CharField(required=True)
    registration_data = serializers.DateTimeField(
        read_only=True, default=serializers.CreateOnlyDefault(datetime.now())
    )
    password = serializers.CharField(
        required=True,
        write_only=True,
        max_length=128,  # Maximum length for Django password
        error_messages={
            'required': 'Please enter a password.',
            'max_length': 'Password should be no more than 128 characters.'
        },
        validators=[
            validators.MinLengthValidator(8, message='Password must be at least 8 characters.'),
            validators.RegexValidator(
                regex=r'[A-Z]',
                message='Password must contain at least one uppercase letter.',
                code='invalid_password'
            ),
            validators.RegexValidator(
                regex=r'[a-z]',
                message='Password must contain at least one lowercase letter.',
                code='invalid_password'
            ),
            validators.RegexValidator(
                regex=r'[0-9]',
                message='Password must contain at least one number.',
                code='invalid_password'
            ),
            validators.RegexValidator(
                regex=r'[!@#$%^&*()]',
                message='Password must contain at least one special character.',
                code='invalid_password'
            )
        ]
    )

    class Meta:
        model = User
        exclude = ['id']


class UserProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    class Meta:
        model = UserProfile
        fields = ('user', 'phone', 'phone_verified', 'email_verified', 'phone_code', 'email_code')
        # exclude = ['id']

views.py:

from django.contrib.auth.models import User
from rest_framework import generics
from .serializer import UserSerializer, UserProfileSerializer

class RegisterUserView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('register/', views.RegisterUserView.as_view(), name='register')
]

Upvotes: 0

Views: 344

Answers (1)

Kikito
Kikito

Reputation: 224

I've noticed that you are experiencing several different errors from your description. Sharing the entire error message can help people to give a more direct answer!

Here are a few suggestions I'd like to make based on common django practices. Might not be the most quick fix but can help you down the way, I hope.

'AttributeError: 'User' object has no attribute 'phone'' in Django

Since django's User model does not have phone field (in currently available Django versions), you added UserProfile model. I think that's great. Along with UserProfile model, if you also define your own custom user model (in the simplest form), it will give you much more flexibility. (ref)

Can be as simple as this:

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    pass

(and if you define a custom user model, one might think 'why not add phone field here?'. yeah, but that depends on your project's requirements. and i think UserProfile as a separate model is still a good choice.bb)

AttributeError at /register/ - Got AttributeError when attempting to get a value for field 'user' on serializer 'UserProfileSerializer'. The serializer field might be named incorrectly and not match any attribute or key on the 'User' instance.

'User' object has no attribute 'user'.

These messages seems incomplete to find a definite answer. But something that can help this sort of issue is letting django know "which is which" using AUTH_USER_MODEL in settings and django's get_user_model.

My goal is to have the nested UserProfileSerializer serialize data from both the user model and the custom UserProfile model.

I assumed that the intention of nested serializer in your code was implementing user registration with required phone number. If that's the case, I think adding a simple custom user model along with your UserProfile could make this easier. and help you debug the errors you shared here.

Hope this helps!

Upvotes: 0

Related Questions