5

I'm using the below serializer for the User model, but when I use depth for handling foreign keys, the password shows in the User object.

User serializer:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        read_only_fields = ('is_active', 'is_staff', 'is_superuser',)
        exclude = ('password', )
        extra_kwargs = {'password': {'write_only': True, 'min_length': 4}}

In below serializer everything is fine:

class AuditSerializer(serializers.ModelSerializer):
    def __init__(self, instance=None, **kwargs):
        if instance:
            setattr(self.Meta, 'depth', 10)
        else:
            setattr(self.Meta, 'depth', 0)
        super(AuditSerializer, self).__init__(instance, **kwargs)

    initiator = UserSerializer(read_only=True)

    class Meta:
        model = Audit
        fields = ['id', 'initiator']
        read_only_fields = ['id', 'initiator']
        depth = 0

But in the below that has relation to the previous model/serializer, I have the password issue:

class AuditAttachmentSerializer(serializers.ModelSerializer):
    def __init__(self, instance=None, **kwargs):
        if instance:
            setattr(self.Meta, 'depth', 10)
        else:
            setattr(self.Meta, 'depth', 0)
        super(AuditAttachmentSerializer, self).__init__(instance, **kwargs)

    class Meta:
        model = AuditAttachment
        fields = ['id', 'audit']
        read_only_fields = ['id']
        depth = 0
JMW
  • 261
  • 2
  • 7
MohammadReza
  • 427
  • 4
  • 16
  • You can not control the fields' nature by using **`depth`** option. For that, you have to use ***nested serialization technique*** (as you have already done that) – JPG Jun 29 '20 at 08:51
  • Apart from that, a quick question, For what purpose did you override the **`__init__()`** method like this? – JPG Jun 29 '20 at 08:52
  • 1
    @ArakkalAbu When I want to add an object by id to `ManyToManyField` the DRF raises an error. – MohammadReza Jun 29 '20 at 09:06
  • 1
    @ArakkalAbu In the *nested serialization technique*, objects won't be added to the nested fields. – MohammadReza Jun 29 '20 at 09:09
  • 2
    I would use this method if I had a choice, [DRF: Simple foreign key assignment with nested serializers?](https://stackoverflow.com/a/52246232/12578202) – JPG Jun 29 '20 at 10:52
  • @ArakkalAbu Thank you, the issue has been resolved. – MohammadReza Jun 29 '20 at 11:36

2 Answers2

2

I had the same problem using the depth Meta attribute. The password was integrated in the serialized data.

1st solution)

Following @JPG comment on the original post, I've used to_representation() method and it works like a charm !

I've ended to this code for the serializer that has a relation with my User model :

from django.contrib.auth.models import Group
from rest_framework import serializers


class BaseGroupSerializer(serializers.ModelSerializer):

    class Meta:
        model = Group
        depth = 1
        fields = (
            'id',
            'name',
            'user_set',
        )
    
    def to_representation(self, instance):
        response = super().to_representation(instance)
        for user in response.get("user_set"):
            user.pop("password", None)
        return response

It simply pops out the password field from each user in my groups.

2nd solution)

An other simple solution would be to directly reference the UserSerializer in which you explicitely excluded the password exclude = ('password',) (or do not include it).

In my case that would've ended up like this :

from django.contrib.auth.models import Group
from rest_framework import serializers
from ..serializers.base_user_serializer import BaseUserSerializer


class BaseGroupSerializer(serializers.ModelSerializer):

    user_set = BaseUserSerializer(many=True)       # <------

    class Meta:
        model = Group
        depth = 1
        fields = (
            'id',
            'name',
            'user_set',
        )

with the BaseUserSerializer as is :

from rest_framework import serializers
from ..models.base_user import User


class BaseUserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        depth = 1
        fields = (
            'id',
            'username',
            'email',
            'first_name',
            'last_name',
            'full_name',
            'full_identification',
            'is_active',
            'groups',
            # 'password' is omitted here
        )

Both ways work. The only problem with the second approach is that you, in some cases, face circular imports if you also import this BaseGroupSerializer in the BaseUserSerializer.

So depending on your case and your limitations with imports,... chose your solution :)

lbris
  • 1,068
  • 11
  • 34
0

I delete the __init__ method and changed it to the below solution.

DRF: Simple foreign key assignment with nested serializers?

MohammadReza
  • 427
  • 4
  • 16