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

HUE-1915 [core] MultipleObjectsReturned for tags or permissions

Only a strict unique clause in a DB could prevent duplicate tags or permissions
to be created. We clean them up at access time instead of filing as it is safe
to delete the duplicates.

Strick DB that fails when installing the Hue example should click on each individual
example install insteaf of the install all button.
Romain Rigaux 12 лет назад
Родитель
Сommit
9173a45
2 измененных файлов с 51 добавлено и 11 удалено
  1. 24 0
      desktop/core/src/desktop/api_tests.py
  2. 27 11
      desktop/core/src/desktop/models.py

+ 24 - 0
desktop/core/src/desktop/api_tests.py

@@ -63,6 +63,30 @@ class TestDocModelTags():
 
 
     assert_true(DocumentTag.objects.filter(id=tag_id, owner=self.user, tag='my_tag').exists())
     assert_true(DocumentTag.objects.filter(id=tag_id, owner=self.user, tag='my_tag').exists())
 
 
+  def test_add_duplicate_tag(self):
+    tag_name = 'test_add_duplicate_tag'
+    n = DocumentTag.objects.filter(owner=self.user, tag=tag_name).count()
+
+    tag_id = self.add_tag(tag_name)
+    assert_equal(n + 1, DocumentTag.objects.filter(owner=self.user, tag=tag_name).count())
+
+    tag_id = self.add_tag(tag_name)
+    assert_equal(n + 1, DocumentTag.objects.filter(owner=self.user, tag=tag_name).count())
+
+  def test_add_and_clean_duplicate_tag(self):
+    tag_name = 'test_add_and_clean_duplicate_tag'
+    script, doc = self.add_doc('test-pig')
+    n = DocumentTag.objects.filter(owner=self.user, tag=tag_name).count()
+
+    tag_id = self.add_tag(tag_name)
+    assert_equal(n + 1, DocumentTag.objects.filter(owner=self.user, tag=tag_name).count())
+
+    DocumentTag.objects.create(owner=self.user, tag=tag_name)
+    assert_equal(n + 2, DocumentTag.objects.filter(owner=self.user, tag=tag_name).count())
+
+    tag_id = DocumentTag.objects.tag(self.user, doc.id, tag_name=tag_name)
+    assert_equal(n + 1, DocumentTag.objects.filter(owner=self.user, tag=tag_name).count())
+
   def test_remove_tags(self):
   def test_remove_tags(self):
     response = self.client.post("/desktop/api/tag/add_tag", {'name': 'my_tag'})
     response = self.client.post("/desktop/api/tag/add_tag", {'name': 'my_tag'})
     tag_id = json.loads(response.content)['tag_id']
     tag_id = json.loads(response.content)['tag_id']

+ 27 - 11
desktop/core/src/desktop/models.py

@@ -77,21 +77,29 @@ class DocumentTagManager(models.Manager):
       tag, created = DocumentTag.objects.get_or_create(tag=tag_name, owner=owner)
       tag, created = DocumentTag.objects.get_or_create(tag=tag_name, owner=owner)
       return tag
       return tag
 
 
-  def get_default_tag(self, user):
-    tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.DEFAULT)
+  def _get_tag(self, user, name):
+    try:
+      tag, created = DocumentTag.objects.get_or_create(owner=user, tag=name)
+    except DocumentTag.MultipleObjectsReturned, ex:
+      # We can delete duplicate tags of a user
+      dups = DocumentTag.objects.filter(owner=user, tag=name)
+      tag = dups[0]
+      for dup in dups[1:]:
+        LOG.warn('Deleting duplicate %s' % dup)
+        dup.delete()
     return tag
     return tag
 
 
+  def get_default_tag(self, user):
+    return self._get_tag(user, DocumentTag.DEFAULT)
+
   def get_trash_tag(self, user):
   def get_trash_tag(self, user):
-    tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.TRASH)
-    return tag
+    return self._get_tag(user, DocumentTag.TRASH)
 
 
   def get_history_tag(self, user):
   def get_history_tag(self, user):
-    tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.HISTORY)
-    return tag
+    return self._get_tag(user, DocumentTag.HISTORY)
 
 
   def get_example_tag(self, user):
   def get_example_tag(self, user):
-    tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.EXAMPLE)
-    return tag
+    return self._get_tag(user, DocumentTag.EXAMPLE)
 
 
   def tag(self, owner, doc_id, tag_name='', tag_id=None):
   def tag(self, owner, doc_id, tag_name='', tag_id=None):
     try:
     try:
@@ -99,7 +107,7 @@ class DocumentTagManager(models.Manager):
       if tag.tag in DocumentTag.RESERVED:
       if tag.tag in DocumentTag.RESERVED:
         raise Exception(_("Can't add %s: it is a reserved tag.") % tag)
         raise Exception(_("Can't add %s: it is a reserved tag.") % tag)
     except DocumentTag.DoesNotExist:
     except DocumentTag.DoesNotExist:
-      tag = DocumentTag.objects.create(tag=tag_name, owner=owner)
+      tag = self._get_tag(user=owner, name=tag_name)
 
 
     doc = Document.objects.get_doc(doc_id, owner)
     doc = Document.objects.get_doc(doc_id, owner)
     doc.add_tag(tag)
     doc.add_tag(tag)
@@ -532,7 +540,15 @@ class DocumentPermissionManager(models.Manager):
       perm.delete()
       perm.delete()
 
 
   def list(self, document):
   def list(self, document):
-    perm, created = DocumentPermission.objects.get_or_create(doc=document, perms=DocumentPermission.READ_PERM)
+    try:
+      perm, created = DocumentPermission.objects.get_or_create(doc=document, perms=DocumentPermission.READ_PERM)
+    except DocumentPermission.MultipleObjectsReturned, ex:
+      # We can delete duplicate perms of a document
+      dups = DocumentPermission.objects.filter(doc=document, perms=DocumentPermission.READ_PERM)
+      perm = dups[0]
+      for dup in dups[1:]:
+        LOG.warn('Deleting duplicate %s' % dup)
+        dup.delete()
     return perm
     return perm
 
 
 
 
@@ -547,7 +563,7 @@ class DocumentPermission(models.Model):
 
 
 
 
   objects = DocumentPermissionManager()
   objects = DocumentPermissionManager()
-  #unique_together = ('doc', 'perms')
+  unique_together = ('doc', 'perms')
 
 
 
 
 # HistoryTable
 # HistoryTable