Jazure
Jazure

Reputation: 501

How to assign existing objects into a Many-to-One relationship using Django-Rest-Framework?

I have a Many-To-One foreign key relationship between Users and a Company. In order to add users to a company, I need to use reverse relations. Each Company has many users. Using the python shell, I can add existing users to a company by doing:

company.user_set.add(user)

I'm stuck on how to perform the same operation on a serializer. I'm able to PATCH a list of users, and it will save the relationship, but I want to append a user instead of overwriting all of them every time. I've seen suggestions such as getting the current list of users and appending a new user, and then saving the new list. I don't know how to implement that function though.

class Company(models.Model):

    company_name = models.CharField(max_length=255)
    address = models.CharField(max_length=255)
    state = models.CharField(max_length=255)
    city = models.CharField(max_length=255)

class User(AbstractBaseUser):

    email = models.EmailField(max_length=255, unique=True)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    USERNAME_FIELD = 'email'

    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True)

    objects = UserManager()


class CompanyUpdateSerializer(serializers.ModelSerializer):

    user_set = UserSerializer(many=True)

    class Meta:
        model = Company
        fields = ('company_name', 'user_set',)

    def to_internal_value(self, data):
        self.fields['user_set'] = serializers.SlugRelatedField(
            queryset=User.objects.all(), many=True, slug_field='email')
        return super(CompanyUpdateSerializer, self).to_internal_value(data)

Upvotes: 0

Views: 1128

Answers (1)

Enthusiast Martin
Enthusiast Martin

Reputation: 3091

You can do in this way. In your serializer:

class CompanyUpdateSerializer(serializers.ModelSerializer):

    users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), write_only=True)

    user_set = UserSerializer(many=True, read_only=True)

    class Meta:
        model = Company
        fields = ('company_name', 'user_set', 'users')

    def update(self, instance, validated_data):

        users = validated_data.pop('users', None)

        instance = super().update(instance, validated_data)

        if users:
            for user in users:
                instance.user_set.add(user)
            instance.save()
        return instance

Now, you do PATCH request with:

{ "users" : [1,2] }

And users with IDs 1 and 2 will be added.

Upvotes: 1

Related Questions