rediet yosef
rediet yosef

Reputation: 222

DRF nested serializer issue on create

I have a User model and a phone model the phone model has a foreign key relation with the user model I read the docs on NestedSerializers and tried it to no avail.

The model

class Phone(models.Model):
    phone = models.CharField(
        _("phone number"), max_length=13, blank=True, null=True)
    otp = IntegerRangeField(min_value=6, max_value=6, blank=True, null=True)
    
    def __str__(self):
        return self.phone


class User(AbstractBaseUser, PermissionsMixin):

    phone = models.ForeignKey(
            Phone, on_delete=models.CASCADE, related_name="userphone", blank=False, null=True)

this is my serializers.py file

class PhoneSerializer(serializers.ModelSerializer):
    # opt = serializers.IntegerField(read_only=True)

    class Meta:
        model = Phone
        fields = ['phone']


    class RegisterSerializerBase(serializers.ModelSerializer):
        phone = PhoneSerializer(allow_null=True)
        # otp = PhoneSerializer(many=True, read_only=True)
        email = serializers.EmailField(
            required=True,
            validators=[UniqueValidator(queryset=User.objects.all())])
    
        password = serializers.CharField(
            write_only=True, re

quired=True, validators=[validate_password])
    password2 = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = User
        fields = ('email', 'firstname', 'lastname', 'password', 'password2',
                  'phone',)
        extra_kwargs = {'password': {'write_only': True},
                        'password2': {'write_only': True},
                        'firstname': {'required': True},
                        'lastname': {'required': True},
                        }

    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError(
                {"password": "Password fields didn't match."})

        return attrs

    def create(self, validated_data):
        phones = validated_data.pop('phone')
        instance = User.objects.create(
            email=validated_data['email'],
            firstname=validated_data['firstname'],
            lastname=validated_data['lastname'],
            is_active='True',
            type=User.TYPES.OWNER,
        )
        instance.set_password(validated_data['password'])
        for phone in phones:
            Phone.objects.create(instance=instance, **phone)
        instance.save()

        return instance

when I go the the Browsable API and create a user with the credentials an error comes up saying

django.db.models.manager.BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method() argument after ** must be a mapping, not str

Upvotes: 0

Views: 561

Answers (1)

Ranu Vijay
Ranu Vijay

Reputation: 1247

Check if this helps you -

Models - User model is already defined.

class Phone(models.Model):
    user = models.Foerienkey(User, related_name="abc")
    phone = models.CharField(max_length=13, blank=True, null=True)

Serializer -

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

class CurrentUserSerializer(serializers.Serializer):
    abc = phoneserializer(many=True, required=False)
    ## define phone serializer before currentuser serializer
    class Meta:
        model = User
        fields = ('username', 'email', 'id', 'abc')

Views -

##user create method

 def create(self, validated_data):
        phones = validated_data.pop('recievedPhoneDataArray')
        instance = User.objects.create(
            email=validated_data['email'],
            firstname=validated_data['firstname'],
            lastname=validated_data['lastname'],
            is_active='True',
            type=User.TYPES.OWNER,
        )
        instance.set_password(validated_data['password'])
        for phone in phones:
            Phone.objects.create(user=instance, **phone)
        instance.save()

        return instance

You will have to extend the registeruserserializer from rest frameowrk. may be.

Upvotes: 1

Related Questions