Django Can't Update Both Custom User and UserProfile Models

76 views Asked by At

I'm working on a Django project, and I'm encountering some issues with my test cases. Specifically, I'm having problems with two test cases related to user profile updates and user creation.

Could someone please help me identify what might be causing these test failures and how to fix them? Any insights or guidance would be greatly appreciated.

Here's the error message I'm getting:

======================================================================
FAIL: test_update_user_profile (user.tests.test_user_api.PrivateUserApiTests)
Test updating the user profile for the authenticated user.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/app/user/tests/test_user_api.py", line 301, in test_update_user_profile
    self.assertEqual(self.profile.bio, payload['profile']['bio'])
AssertionError: 'Profile bio.' != 'Updated bio.'
- Profile bio.
+ Updated bio.
======================================================================
FAIL: test_create_user_success (user.tests.test_user_api.PublicUserApiTests)
Test creating a user is successfull.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/app/user/tests/test_user_api.py", line 95, in test_create_user_success
    self.assertEqual(res.status_code, status.HTTP_201_CREATED)
AssertionError: 400 != 201

test_user_api.py

CREATE_USER_URL = reverse('user:create')
ME_URL = reverse('user:me')

def create_user(**params):
    return get_user_model().objects.create_user(**params)

def create_profile(user, **params):
    defaults = {
        'picture': None,
        'bio': 'My bio.',
        'dob': '2000-12-12',
    }
    defaults.update(params)
    return UserProfile.objects.create(user=user, **defaults)


class PublicUserApiTests(TestCase):

    def setUp(self):
        self.client = APIClient()

    def test_create_user_success(self):
        payload = {
            'name': 'Test Name',
            'email': '[email protected]',
            'password': 'testpass123',
            'profile': {
                'picture': None,
                'bio': 'Create bio.',
                'dob': '2000-01-01',
            }
        }
        res = self.client.post(CREATE_USER_URL, payload, content_type='application/json')
        self.assertEqual(res.status_code, status.HTTP_201_CREATED)


class PrivateUserApiTests(TestCase):
    """Test API requests that require authentication."""

    def setUp(self):
        self.user = create_user(
            name='Test Name',
            email='[email protected]',
            password='testpass123',
        )
        self.profile = create_profile(
            user=self.user,
            picture=None,
            bio="Profile bio.",
            dob="2017-05-27",
        )
        self.client = APIClient()
        self.client.force_authenticate(user=self.user)

    def test_update_user_profile(self):
        payload = {
            'name': 'Updated Name',
            'email': '[email protected]',
            'password': 'newpassword123',
            'profile': {
                'picture': None,
                'bio': 'Updated bio.',
                'dob': '2022-02-02',
                }
        }
        res_profile = self.client.patch(ME_URL, payload, format='json')
        self.user.refresh_from_db
        self.profile.refresh_from_db()
        self.assertEqual(self.profile.bio, payload['profile']['bio'])

Urls.py:

path('create/', views.CreateUserView.as_view(), name='create'),
path('me/', views.ManageUserView.as_view(), name='me'),

Models.py:

class UserManager(BaseUserManager):

    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('User must have an email address.')

        user = self.model(email=self.normalize_email(email), **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(max_length=225, unique=True)
    name = models.CharField(max_length=225)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    objects = UserManager()
    USERNAME_FIELD = 'email'


class UserProfile(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='userprofile')
    picture = models.ImageField(null=True, blank=True, upload_to=image_file_path)
    bio = models.CharField(max_length=225, blank=True)
    dob = models.DateField()
    created_on = models.DateTimeField(auto_now_add=True)

    def name(self, value):
        self.user.name = value
        self.user.save()

    def email(self, value):
        self.user.email = value
        self.user.save()

    def __str__(self):
        return self.user.email

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

Views.py:

class CreateUserView(generics.CreateAPIView):
    serializer_class = UserSerializer


class ManageUserView(generics.RetrieveUpdateAPIView):

    serializer_class = UserSerializer
    authentication_classes = (JWTAuthentication, )
    permission_classes = [permissions.IsAuthenticated]

    def get_object(self):
        return self.request.user

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)

Serializers.py:

class UserProfileSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserProfile
        fields =  ['picture', 'bio', 'dob']


class UserSerializer(serializers.ModelSerializer):

    profile = UserProfileSerializer(source="userprofile", many=False)

    class Meta:
        model = get_user_model()
        fields = ['name', 'email', 'password', 'profile']
        extra_kwargs = {'password': {'write_only': True, 'min_length': 5}}

    def get_token(self, obj):
        token = RefreshToken.for_user(obj)
        return str(token.access_token)

    def create(self, validated_data):
        return get_user_model().objects.create_user(**validated_data)

    def update(self, instance, validated_data):

        password = validated_data.pop('password', None)
        if password:
            instance.set_password(password)
            instance.save()

        profile_data = validated_data.pop('profile', None)
        if profile_data is not None:
            instance.profile.picture = profile_data['picture']
            instance.profile.bio = profile_data['bio']
            instance.profile.dob = profile_data['dob']           
            instance.profile.save()
        return super().update(instance, validated_data)

    def get_name(self, obj):
        return obj.name

    def get_id(self, obj):
        return obj.id

Thank you in advance for your assistance!

0

There are 0 answers