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
...