Home > Back-end >  Only id is returing in nested serializer django rest framework
Only id is returing in nested serializer django rest framework

Time:10-04

I have two models user and notes, my aim is to get a JSON response like this.

{
"status": 200,
"data": [
    {
        "id": 1,
        "note": "dd",
        "created_on": "2022-10-03T06:58:33.337137Z",
        "is_active": true,
        "created_by":[{
           "username":"loream",
           "email":"[email protected]",
           ...........

         }
       ]
    },
    
]}

Modals are :

class Notes(models.Model):
   note= models.TextField()
   created_on=models.DateTimeField(auto_now_add=True)
   is_active=models.BooleanField(default=True)
user=models.ForeignKey(UserModal,on_delete=models.CASCADE,null=True,related_name="created_byy",blank=True)



class UserModal(AbstractUser):
  username = models.CharField(max_length=30,unique=True)
  password = models.CharField(max_length=30)
  email = models.EmailField(blank=True)

serializers I wrote is

class UserSerializer(serializers.ModelSerializer):

   class Meta:
     model = UserModal
     fields = '__all__'

class NotesSerializer(serializers.ModelSerializer):
   created_byy = UserSerializer(many=True,read_only=True)
   class Meta:
     model=Notes
    fields='__all__'

But I couldn't get a JSON response as expected I'm getting responses like this

{
"status": 200,
"data": [
    {
        "id": 1,
        "note": "dd",
        "created_on": "2022-10-03T06:58:33.337137Z",
        "is_active": true,
        "user": 1
    },
    
]

}

how can I achieve the expected result?

CodePudding user response:

To fix this, change your serializer as follows:

class NotesSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)  # user instead of created_byy, and no many=True
    class Meta:
        model = Notes
        fields = '__all__'

Some explanations:
The problem you have is created_byy does not exist in your Notes model, it's the name of the attribute to get the queryset of notes from a user instance.
Basically, using user.created_byy.all() would get you all notes related to this user.
Mode details about related_name in this post.

user is the attribute you declared in your model, that's why you still retrieve it when using fields='__all__', and that's definitely the one you want.

If you really want your user to be named "created_by", just use a SerializerMethodField (docs here):

class NotesSerializer(serializers.ModelSerializer):
    created_by = serializers.SerializerMethodField()

    def get_created_by(self, instance):
        return UserSerializer(instance.user)

    class Meta:
        model = Notes
        fields = ['id', 'note', 'created_on', 'created_by', 'is_active']

Also, you cannot have an array of users in both cases, because of how you declared your one-to-many (one user can have several notes, the opposite is false).

On a final note, you really should rename the created_byy to notes so it's less confusing.

CodePudding user response:

@ThomasGth give you nice explanation.

Here is quick solution from me

class NotesSerializer(serializers.ModelSerializer):
    created_by = UserSerializer(source='user', read_only=True)

    class Meta:
        model = Notes
        fields = ['id', 'note', 'created_on', 'created_by', 'is_active']
  • Related