2

I am a beginner in Django. Right now, I am working with the APIs. I am facing a problem. I can't view the string value one of the fields, called label, at http://127.0.0.1:8000/gameapi/. Instead of seeing "label_tag": "racing", I am seeing "label_tag": [2]. Here is the screenshot: enter image description here

Here are my codes of serializers.py located inside gamreview folder.

from rest_framework import serializers
from .models import Game, Tags


# class TagSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Tags
#         fields = ['label']

class GameSerializer(serializers.ModelSerializer):
    # label_tag = TagSerializer(many=True)
    class Meta:
        model = Game
        # fields = ['id', 'title', 'developer', 'platform']
        fields = ['id', 'title', 'developer', 'platform','label_tag']

def create(self, validated_data):
    label_tag_data = validated_data.pop('label_tag')
    game = Game.objects.create(**validated_data)
    for tags_data in label_tag_data:
        Tags.objects.create(game=game, **tags_data)
    return Game.objects.create(**validated_data)

def update(self, instance, validated_data):
    instance.title = validated_data.get('title', instance.title)
    instance.developer = validated_data.get('developer', instance.developer)
    instance.platform = validated_data.get('platform', instance.platform)
    # instance.tag = TagSerializer(read_only=True, many=True)
    instance.save()
    return instance

Here are my codes of models.py under gamreview folder:

from django.db import models
from django.template.defaultfilters import slugify

# Create your models here.

class Tags(models.Model):
    label = models.CharField(max_length=20)

    def __str__(self):
        return self.label


class Game(models.Model):
    title = models.CharField(max_length=100)
    developer = models.CharField(max_length=100)
    platform = models.CharField(max_length=50, default='null')
    label_tag = models.ManyToManyField(Tags)
    slug = models.SlugField(max_length=150, default='null')

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super().save(*args, **kwargs)


class Review(models.Model):
    game = models.ForeignKey(Game, on_delete=models.CASCADE)
    review = models.CharField(max_length=1000)
    date = models.DateField(auto_now=True)
    slug = models.SlugField(max_length=150, default='null')

    def __str__(self):
        return self.game

Here are my codes of views.py under gamreview folder:

from django.views import generic
from .models import Game
from rest_framework import generics
from .serializers import GameSerializer


# Create your views here.


class GameListView(generic.ListView):
    template_name = 'gamereview/gamelist.html'
    context_object_name = 'all_games'

    def get_queryset(self):
        return Game.objects.all()


class ReviewView(generic.DetailView):
    model = Game
    template_name = 'gamereview/review.html'

# class GameApiView(generics.ListAPIView):
class GameApiView(generics.ListCreateAPIView):
    queryset = Game.objects.all()
    serializer_class = GameSerializer

class GameDetailApiView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Game.objects.all()
    serializer_class = GameSerializer

Here are my codes of urls.py under gamreview folder:

from . import views
from django.urls import path

app_name = 'gamereview'

urlpatterns = [
    path('gamereview/', views.GameListView.as_view(), name='gamelist'),
    path('gamereview/<slug:slug>/', views.ReviewView.as_view(), name='review'),
    path('gameapi/', views.GameApiView.as_view(), name='gamelistapi'),
    path('gameapi/<int:pk>/', views.GameDetailApiView.as_view()),


]

I don't get any error while running the server. However, "label_tag": "racing"is not showing up. How can I fix the issue?

2 Answers 2

2

in Game model change label_tag to

label_tag = models.ManyToManyField(Tags, related_name='tags')

this can be considered as tags is a field for a Game model your serializer classes should be

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tags
        fields = ['label']

class GameSerializer(serializers.ModelSerializer):
    tags= TagSerializer(many=True)
    class Meta:
        model = Game
        # fields = ['id', 'title', 'developer', 'platform']
        fields = ['id', 'title', 'developer', 'platform','tags']

you will get tags as a list of tags objects every tag have a label field with string value

'tags': [
    {
        'label': 'etc'
    },
    {
        'label': 'etc2'
    }
]

if you want tags like

'tags': [
    'etc',
    'etc'
]

this code will help you 
```python
class GameSerializer(serializers.ModelSerializer):
    label_tags = serializers.SerializerMethodField()
    class Meta:
        model = Game
        # fields = ['id', 'title', 'developer', 'platform']
        fields = ['id', 'title', 'developer', 'platform','label_tags']

    def get_label_tags(self, game):
        new_tags = []
        tags = game.label_tag.all()
        for tag in tags:
            new_tags.append(tag.label)
        return new_tags
Sign up to request clarification or add additional context in comments.

2 Comments

The second code works for me. However, I am not getting output like this: 'tags': [ 'etc', 'etc' ] Instead, I am getting output like this: 'label_tags': [ 'etc', 'etc' ] How can I make 'label_tags' to 'tags'?
label_tags = serializers.SerializerMethodField() >> tags = serializers.SerializerMethodField() and fields = ['id', 'title', 'developer', 'platform','label_tags'] >> fields = ['id', 'title', 'developer', 'platform','tags'] and def get_label_tags(self, game): >> def get_tags(self, game):
-1

You can use the source argument

 class GameSerializer(serializers.ModelSerializer):
        label_tag = serializers.ReadOnlyField(source='label.label')
        class Meta:
            model = Game
            fields = ['id', 'title', 'developer', 'platform','label_tag']

another way is to use a SerializerMethodField like this(it's an overkill in this case I believe)

 class GameSerializer(serializers.ModelSerializer):
        label_tag = serializers.SerializerMethodField()
        class Meta:
            model = Game
            fields = ['id', 'title', 'developer', 'platform','label_tag'] 

        def get_label_tag(self, obj):
            return obj.label.label

check similar answers here DRF source argument

2 Comments

When I use your codes of source argument, "label_tag": [2] got disappeared. And when I use your codes of SerializerMethodField, I got this error: AttributeError at /gameapi/ 'Game' object has no attribute 'label'
use obj.label for the second one

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.