Home > Mobile >  How to validade traverse attributes in DRF Serializer?
How to validade traverse attributes in DRF Serializer?

Time:07-29

So, trying to be as brief as possible and to put my problem into context, I will tell you here my doubt. The problem is that I don't know how to serialize the data in a correct way. How do I validadte traverse attributes inside serializer?

My data model is structured as follows, an employee belongs to a company unity, and this unity belongs to a company, and there is also a super administrator who can access the data of all the other users.

# models.py
class User(AbstractUser):
    class Roles(models.IntegerChoices):
        SUPER = 0, _('SuperAdmins')
        COMPANY = 1, _('Company')
        UNITY = 2, _('Unity')
        STAFF = 3, _('Staff')
        
    role: Roles = models.PositiveSmallIntegerField(choices=Roles.choices, default=Roles.STAFF, verbose_name=_("Role"))
    objects = UserManager()


class Company(TimeStampedModel):
    user: User = models.OneToOneField(User, null=True, on_delete=models.CASCADE, verbose_name=_("User"))
    cnpj: str = BRCNPJField(_("CNPJ"), unique=True)



class Unity(TimeStampedModel):
    user: User = models.OneToOneField(User, null=True, on_delete=models.CASCADE, verbose_name=_("Usuário"))
    postal_code: str = BRPostalCodeField(verbose_name=_("CEP"), unique=False)
    company = models.ForeignKey(Company, related_name='units', on_delete=models.CASCADE, verbose_name=_("Compania"))



class Staff(TimeStampedModel):
    user: User = models.OneToOneField(User, null=True, on_delete=models.CASCADE, verbose_name=_("User"))
    unity = models.ForeignKey(Unity, related_name="staffs", on_delete=models.CASCADE, verbose_name=_("Unity"))
    cpf = BRCPFField(_("CPF"))


My serializer looks like:

class RegisterStaffSerializerForModerators(serializers.ModelSerializer):
    """
    The main goal of this
    """
    username = serializers.CharField(source="user.username", max_length=150, allow_blank=True,
                                     validators=[username_validator], )
    email = serializers.EmailField(source="user.email", allow_blank=True, max_length=150)
    first_name = serializers.CharField(source="user.first_name", allow_blank=True, max_length=150)
    last_name = serializers.CharField(source="user.last_name", allow_blank=True, max_length=150)
    password = serializers.CharField(source="user.password", write_only=True, max_length=150)
    is_active = serializers.BooleanField(source="user.is_active", read_only=True)

    class Meta:
        model = Staff
        fields = ('id',
                  'email',
                  "username",
                  'first_name',
                  'last_name',
                  'password',
                  'is_active',
                  "unity",
                  "cpf"
                  )
        extra_kwargs = {
            'is_active': {'read_only': True},
            'password': {'write_only': True},
            "id": {"read_only": True}
        }

    # def validate(self, attrs):
    #     email = attrs.get("email", "")
    #     print(attrs)
    #     return super(RegisterStaffSerializerForModerators, self).validate(attrs)

    def create(self, validated_data):
        user_data = validated_data["user"]
        user = User.objects.create_user(
            username=user_data.get('username'),
            email=user_data.get('email'),
            first_name=user_data.get("first_name"),
            password=user_data.get('password')

        )

        staff = Staff.objects.create_staff(user=user, unity=validated_data.get("unity"), cpf=validated_data.get("cpf"))
        return staff

To register a new staff member I need to validate the transverse attrs, but I don't want to overwrite the method of validating data and validating each field, couldn't I import the conditions from the class I am using as a base? For example: username and e-mail be unique?

CodePudding user response:

I think you could use the UserSerializer.

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

class RegisterStaffSerializerForModerators(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = Staff
        ...
  • Related