ValueError: Cannot query "User.name": Must be "Model" instance

45 Views Asked by At

I am facing an issue with querying the Profile model based on the user_id of a Project instance in my Django REST framework project. When attempting to retrieve the profile using the user_id, I receive a ValueError with the message "Cannot query 'Shahryar Bin Talib': Must be 'Project' instance."

I have a Profile model with a one-to-one relationship with the built-in User model. The Project model has a foreign key relationship with the User model, and I want to retrieve the Profile instance related to the specific Project using the user_id. I have checked the profile instance after the query and the profile is retrieved successfully.

Views.py

    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    @action(methods=['get', 'put', 'post'], detail=True, url_name='project_profile', url_path='profile')
    def project_profile(self, request, pk):
        
        try:
            project = Project.objects.get(id=pk)
        except Project.DoesNotExist:
            return Response({'error': 'Project does not exist.'}, status=status.HTTP_404_NOT_FOUND)

        profile = project.user.profile
        serializer = ProfileSerializer(profile)
        return Response(serializer.data)

serializers.py

    user = serializers.ReadOnlyField(source='user.username')
    skills = serializers.StringRelatedField(many=True)
    project = ProjectSerializer(source='user.project', many=True)

    class Meta:
        model = Profile
        exclude = ['bio']

models.py

class Project(TimeStampedModel):
    """ A model representing a project """

    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        blank=True,
        related_name='project',
        help_text='The user that created the project.'
    )
    title = models.CharField(
        max_length=200,
        blank=True,
        null=True,
        help_text='The title of the project.'
    )
    description = models.TextField(
        blank=True,
        null=True,
        help_text='The detailed description of the project.'
    )

class Profile(TimeStampedModel):
    """ Model representing a user profile """

    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        help_text='The related user.'
    )
    skills = SortedManyToManyField(
        'Skill',
        blank=True,
        related_name='profile',
        help_text='The skills associated with the profile.'
    )
    short_intro = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        help_text='A short intro or a post title.'
    )

Here is the pdb: `/Users/uzair.imtiaz/Desktop/Code-Book/api/views.py(41)project_profile() -> try: (Pdb) n

/Users/uzair.imtiaz/Desktop/Code-Book/api/views.py(42)project_profile() -> project = Project.objects.get(id=pk) (Pdb) n /Users/uzair.imtiaz/Desktop/Code-Book/api/views.py(46)project_profile() -> profile = project.user.profile (Pdb) n /Users/uzair.imtiaz/Desktop/Code-Book/api/views.py(47)project_profile() -> serializer = ProfileSerializer(profile) (Pdb) p profile.date_of_birth datetime.date(2002, 8, 14)`

It is not any different than this:

class ProfileViewSet(viewsets.ModelViewSet):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

    @action(methods=['get', 'put', 'post'], detail=True, url_name='profile_projects', url_path='projects')
    def profile_projects(self, request, pk):
        try:
            projects = Project.objects.filter(user_id=pk)
        except Project.DoesNotExist:
            return Response({'error': 'Profile does not exist.'}, status=status.HTTP_404_NOT_FOUND)

        serializer = ProjectSerializer(projects, many=True)
        return Response(serializer.data)

if this is working why is it raising that error on project_profile

1

There are 1 best solutions below

0
Asim Ejaz On

Issue

You're trying to access it like this

Project > User > Profile

While your database relations are like this, Project > User Profile > User

User model doesn't have profile attribute, its the Profile mode which has the user attribute.

Fix

You can define a related_name with user field in Profile Model to access profile from user object

class Profile(TimeStampedModel):
""" Model representing a user profile """

    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        help_text='The related user.',
        related_name="user_profile"
    )
    skills = SortedManyToManyField(
        'Skill',
        blank=True,
        related_name='profile',
        help_text='The skills associated with the profile.'
    )
    short_intro = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        help_text='A short intro or a post title.'
    )

You can then access it like,

project.user.user_profile