I have three models in my models.py as follows:
class Service(models.Model):
name = models.CharField(max_length=50, unique=True)
port = models.PositiveSmallIntegerField()
protocol = models.CharField(max_length=50)
class ServiceGroup(models.Model):
name = models.CharField(max_length=50, unique=True)
services = models.ManyToManyField(Service, through=ServiceToServiceGroup)
class ServiceToServiceGroup(models.Model):
service = models.ForeignKey(Service)
service_group = models.ForeignKey(ServiceGroup)
My JSON payload to create a new service group is as follows:
{
"name": "test_service_group1",
"services":["service_1", "service_2"],
}
Since I have a M2M through table, my strategy to create a new ServiceGroup is to first pop out the services list, create the ServiceGroup with the name and then create the M2M realtionships.
My serializer to create a new ServiceGroup is as follows:
class ServiceGroupCreateUpdateSerializer(serializers.ModelSerializer):
services = serializers.SlugRelatedField(queryset=Service.objects.all(),
slug_field='name', many=True)
class Meta:
model = ServiceGroup
fields = ['id', 'name', 'services']
def create(self, validated_data):
# Pop the services list out
services = validated_data.pop('services', None)
# Create the ServiceGroup with the name
service_group = ServiceGroup.objects.create(name=validated_data['name'])
#Create M2M associations
for service in services:
service_id = Service.objects.get(name=service)
ServiceToServiceGroup.objects.create(service_id=service_id,
service_group_id= service_group.id)
My question is how do I now write the update method ? My JSON payload remains the same, the only difference being that I pass the instance id in the URL.The pseudo code is as follows:
- Pop the services list.
- Save the name to the instance id.
- Find the existing services linked to the ServiceGroup.
- For services common in the existing list and the JSON payload list, do nothing.
- For services in the existing list and not in the payload, delete M2M associations.
- For services not in the existing list and in the payload, create M2M associations.
This seems like so much work for an update method. Is there an easier way of doing this ?
UPDATE
In [145]: instance = ServiceGroup.objects.get(pk=1)
In [146]: instance.services.all()
Out[146]: <QuerySet [<Service: test-create442>]>
In [147]: new_services_list = ['test-create398']
In [148]: service_objects =
Service.objects.filter(name__in=new_services_list).all()
In [149]: service_objects
Out[149]: <QuerySet [<Service: test-create398>]>
In [150]: instance.service_set = service_objects
In [151]: instance.save()
In [152]: instance.services.all()
Out[152]: <QuerySet [<Service: test-create442>]>
So, I tried the above and it did not work.