jdez
jdez

Reputation: 199

How to return correct model fields in serializer?

I am implementing a search bar that returns the users and the posts. I am able to return the data but when I clear the search bar I get the error returned:

AttributeError: Got AttributeError when attempting to get a value for field username on serializer SearchUserSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Post instance. The original exception text was: 'Post' object has no attribute 'username'.

My Models:

class User(AbstractUser):
    avi_pic = models.ImageField(
        max_length=400, null=True, blank=True, upload_to='images')
    name = models.CharField(max_length=50, blank=True, null=True)
    username = models.CharField(max_length=30, unique=True)

class Post(models.Model):
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, default=None
    )
    cover = models.CharField(max_length=300, default='', blank=True)
    title = models.CharField(max_length=300, default='', blank=True)
    date = models.DateTimeField(editable=False, auto_now_add=True)

My Serializers:

class SearchPostSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = ('id', 'title', 'user', 'username', 'cover')

    def get_username(self, post):
        return post.user.username

class SearchUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'name', 'username', 'avi_pic')

and my Views.py:

class SearchView(generics.ListAPIView):

    def get_serializer_class(self):
        queryset = self.get_queryset()
        if len(queryset) == 0:
            return None
        if isinstance(queryset[0], User):
            return SearchUserSerializer
        elif isinstance(queryset[0], Post):
            return SearchPostSerializer
        else:
            return None

    def get_queryset(self):
        query = self.request.query_params.get('q', None)
        if query is not None:
            queryset_users = User.objects.filter(
                Q(name__icontains=query) | Q(username__icontains=query))
            queryset_posts = Post.objects.filter(
                Q(playlist_title__icontains=query))
            results = list(queryset_users) + list(queryset_posts)
            return results
        else:
            return User.objects.none()

I've tried many things with zero luck.

Upvotes: 0

Views: 170

Answers (1)

Arif Rasim
Arif Rasim

Reputation: 167

Try this:

class SearchPostSerializer(serializers.ModelSerializer):
    username = serializers.CharField(source='user.username')
    class Meta:
        model = Post
        fields = ('id', 'title', 'user', 'username', 'cover')

This should do the trick .

You can remove the get_username function

You can take a look here for the explanation:

https://www.django-rest-framework.org/api-guide/fields/#source

Upvotes: 1

Related Questions