Просмотр исходного кода

Fixes #5118: Specifying an empty list of tags should clear assigned tags (REST API)

Jeremy Stretch 5 лет назад
Родитель
Сommit
4466458076
3 измененных файлов с 30 добавлено и 5 удалено
  1. 1 0
      docs/release-notes/version-2.9.md
  2. 11 5
      netbox/extras/api/serializers.py
  3. 18 0
      netbox/extras/tests/test_tags.py

+ 1 - 0
docs/release-notes/version-2.9.md

@@ -7,6 +7,7 @@
 * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release
 * [#5050](https://github.com/netbox-community/netbox/issues/5050) - Fix potential failure on `0016_replicate_interfaces` schema migration from old release
 * [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data
 * [#5109](https://github.com/netbox-community/netbox/issues/5109) - Fix representation of custom choice field values for webhook data
 * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params`
 * [#5111](https://github.com/netbox-community/netbox/issues/5111) - Allow use of tuples when specifying ObjectVar `query_params`
+* [#5118](https://github.com/netbox-community/netbox/issues/5118) - Specifying an empty list of tags should clear assigned tags (REST API)
 
 
 ---
 ---
 
 

+ 11 - 5
netbox/extras/api/serializers.py

@@ -101,24 +101,30 @@ class TaggedObjectSerializer(serializers.Serializer):
     tags = NestedTagSerializer(many=True, required=False)
     tags = NestedTagSerializer(many=True, required=False)
 
 
     def create(self, validated_data):
     def create(self, validated_data):
-        tags = validated_data.pop('tags', [])
+        tags = validated_data.pop('tags', None)
         instance = super().create(validated_data)
         instance = super().create(validated_data)
 
 
-        return self._save_tags(instance, tags)
+        if tags is not None:
+            return self._save_tags(instance, tags)
+        return instance
 
 
     def update(self, instance, validated_data):
     def update(self, instance, validated_data):
-        tags = validated_data.pop('tags', [])
+        tags = validated_data.pop('tags', None)
 
 
         # Cache tags on instance for change logging
         # Cache tags on instance for change logging
-        instance._tags = tags
+        instance._tags = tags or []
 
 
         instance = super().update(instance, validated_data)
         instance = super().update(instance, validated_data)
 
 
-        return self._save_tags(instance, tags)
+        if tags is not None:
+            return self._save_tags(instance, tags)
+        return instance
 
 
     def _save_tags(self, instance, tags):
     def _save_tags(self, instance, tags):
         if tags:
         if tags:
             instance.tags.set(*[t.name for t in tags])
             instance.tags.set(*[t.name for t in tags])
+        else:
+            instance.tags.clear()
 
 
         return instance
         return instance
 
 

+ 18 - 0
netbox/extras/tests/test_tags.py

@@ -59,3 +59,21 @@ class TaggedItemTest(APITestCase):
             sorted([t.name for t in site.tags.all()]),
             sorted([t.name for t in site.tags.all()]),
             sorted(["Foo", "Bar", "New Tag"])
             sorted(["Foo", "Bar", "New Tag"])
         )
         )
+
+    def test_clear_tagged_item(self):
+        site = Site.objects.create(
+            name='Test Site',
+            slug='test-site'
+        )
+        site.tags.add("Foo", "Bar", "Baz")
+        data = {
+            'tags': []
+        }
+        self.add_permissions('dcim.change_site')
+        url = reverse('dcim-api:site-detail', kwargs={'pk': site.pk})
+
+        response = self.client.patch(url, data, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertEqual(len(response.data['tags']), 0)
+        site = Site.objects.get(pk=response.data['id'])
+        self.assertEqual(len(site.tags.all()), 0)