Aarti Joshi
Aarti Joshi

Reputation: 405

How to add extra field to django serializer?

I am trying to add an additional field to my serializer but I am getting the following error:-

"The field 'provider' was declared on serializer CreateUserSerializer, but has not been included in the 'fields' option."

Here is my serializer.py:-


class CreateUserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField()
    username = serializers.CharField()
    company = serializers.CharField()
    provider = serializers.CharField()
    password = serializers.CharField(write_only=True)
    company_detail = serializers.SerializerMethodField()
    branch_detail = serializers.SerializerMethodField()

    def get_company_detail(self):
        return {}

    def get_branch_detail(self):
        return {}

    def create(self, validated_data):
        try:
            with transaction.atomic():
                user = User.objects.create(**validated_data)

                user_profile = UserProfileModel.objects.create(user=user)
                user_profile.__dict__.update(**validated_data)
                user_profile.save()

                identity = FederatedIdentityModel.objects.create(user=user, oauth_provider=validated_data['provider'])

                company = CompanyModel.objects.create(user=user, name=validated_data['company'])

                branch = BranchModel.objects.create(user=user, name=validated_data['company'], company=company)

                return user

        except APIException:
            raise APIException(
                detail="Failed to register",
                code=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'password', 'email', 'username',
                  'company_detail', 'branch_detail']

I don't want to add the company and provider fields in the field option as it is not a part of user model. I just want to use them as writable fields so that I can create object for the two models.

How can I get rid of the following error?

Upvotes: 0

Views: 6390

Answers (2)

Aarti Joshi
Aarti Joshi

Reputation: 405

I found an alternative to solve this problem:-

class CreateUserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField()
    company = serializers.CharField(write_only=True)
    provider = serializers.ChoiceField(write_only=True, choices=OAUTH_PROVIDER_CHOICES)
    password = serializers.CharField(write_only=True)
    company_detail = serializers.SerializerMethodField()
    branch_detail = serializers.SerializerMethodField()

    # to get the details of company in response body
    def get_company_detail(self, obj):
        return {}

    # to get the details of branch in response body
    def get_branch_detail(self, obj):
        return {}

    def create(self, validated_data):
        # pop additional fields from validated data to avoid error
        company_name = validated_data.pop('company', None)
        provider = validated_data.pop('provider', None)
        try:
            with transaction.atomic():
                # create a user object
                user = User.objects.create(**validated_data)
                # create a user profile object
                user_profile = UserProfileModel.objects.create(user=user)
                user_profile.__dict__.update(**validated_data)
                user_profile.save()
                # create federated identity object using provider and email
                identity = FederatedIdentityModel.objects.create(user=user, oauth_provider=provider,
                                                                 email=validated_data['email'])
                # create company object
                company = CompanyModel.objects.create(user=user, name=company_name)

                return user

        except APIException:
            raise APIException(
                detail="Failed to register",
                code=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'password', 'email', 'username',
                  'company', 'provider', 'company_detail', 'branch_detail']

while creating user, I am popping the extra fields and using the popped value as the value while creating specific objects and adding the write_only=True in fields. In that case, I can add the fields in my field_list without getting any error

Upvotes: 0

Charnel
Charnel

Reputation: 4432

I think you can't use that field without adding it to fields. What you can do is simply split model & extra fields into two lists and then define:

provider = serializers.CharField()
company = serializers.CharField()
...
class Meta:
    model = User
    model_fields = ['first_name', 'last_name', 'password', 'email', 'username',
              'company_detail', 'branch_detail']
    extra_fields = ['company', 'provider']
    fields = model_fields + extra_fields

Upvotes: 3

Related Questions