Permalink
Browse files

Check category slug uniqueness taking parent into consideration

  • Loading branch information...
1 parent 9ff5201 commit 6b4437d8bdee94b33301607f1e659e5eefd8b1c7 @fjern fjern committed Jun 20, 2012
Showing with 97 additions and 13 deletions.
  1. +36 −12 oscar/apps/dashboard/catalogue/forms.py
  2. +61 −1 oscar/apps/dashboard/catalogue/tests.py
@@ -16,19 +16,43 @@
class CategoryForm(MoveNodeForm):
- def clean_name(self):
- name = self.cleaned_data['name']
- if name:
- slug = slugify(name)
- try:
- category = Category.objects.get(slug=slug)
- except Category.DoesNotExist:
- pass
- else:
- if category.pk != self.instance.pk:
- raise forms.ValidationError(_('Category with the given name'
+ def clean(self):
+ cleaned_data = super(CategoryForm, self).clean()
+
+ name = cleaned_data['name']
+ ref_node_pk = cleaned_data['_ref_node_id']
+ pos = cleaned_data['_position']
+
+ if name and self.is_slug_conflicting(name, ref_node_pk, pos):
+ raise forms.ValidationError(_('Category with the given path'
' already exists.'))
- return name
+ return cleaned_data
+
+ def is_slug_conflicting(self, name, ref_node_pk, position):
+
+ #determine parent
+ if ref_node_pk:
+ ref_category = Category.objects.get(pk=ref_node_pk)
+ if position == 'first-child':
+ parent = ref_category
+ else:
+ parent = ref_category.get_parent()
+ else:
+ parent = None
+
+ #build full slug
+ slug_prefix = (parent.slug + Category._slug_separator) if parent else ''
+ slug = '%s%s' % (slug_prefix, slugify(name))
+
+ #check if slug is conflicting
+ try:
+ category = Category.objects.get(slug=slug)
+ except Category.DoesNotExist:
+ pass
+ else:
+ if category.pk != self.instance.pk:
+ return True
+ return False
class Meta(MoveNodeForm.Meta):
model = Category
@@ -1,6 +1,10 @@
from django.core.urlresolvers import reverse
+from django.test import TestCase
from oscar.test import ClientTestCase
+from oscar.apps.catalogue.models import Category
+from oscar.apps.dashboard.catalogue.forms import CategoryForm
+from oscar.apps.catalogue.categories import create_from_breadcrumbs
class ViewTests(ClientTestCase):
@@ -11,4 +15,60 @@ def test_pages_exist(self):
reverse('dashboard:stock-alert-list'),
]
for url in urls:
- self.assertIsOk(self.client.get(url))
+ self.assertIsOk(self.client.get(url))
+
+
+
+class CategoryFormTests(TestCase):
+
+ def setUp(self):
+ Category.objects.all().delete()
+
+ def test_conflicting_slugs_recognized(self):
+ trail = 'A > B > C'
+ create_from_breadcrumbs(trail)
+ trail = 'A > B > D'
+ create_from_breadcrumbs(trail)
+ trail = 'A > E > F'
+ create_from_breadcrumbs(trail)
+ trail = 'A > E > G'
+ create_from_breadcrumbs(trail)
+
+ f = CategoryForm()
+
+ #root categories
+ ref_node_pk = Category.objects.get(name='A').pk
+ conflicting = f.is_slug_conflicting('A', ref_node_pk, 'right')
+ self.assertEqual(conflicting, True)
+
+ conflicting = f.is_slug_conflicting('A', None, 'left')
+ self.assertEqual(conflicting, True)
+
+ conflicting = f.is_slug_conflicting('A', None, 'first-child')
+ self.assertEqual(conflicting, True)
+
+ conflicting = f.is_slug_conflicting('B', None, 'left')
+ self.assertEqual(conflicting, False)
+
+ #subcategories
+ ref_node_pk = Category.objects.get(name='C').pk
+ conflicting = f.is_slug_conflicting('D', ref_node_pk, 'left')
+ self.assertEqual(conflicting, True)
+
+ ref_node_pk = Category.objects.get(name='B').pk
+ conflicting = f.is_slug_conflicting('D', ref_node_pk, 'first-child')
+ self.assertEqual(conflicting, True)
+
+ ref_node_pk = Category.objects.get(name='F').pk
+ conflicting = f.is_slug_conflicting('D', ref_node_pk, 'left')
+ self.assertEqual(conflicting, False)
+
+ ref_node_pk = Category.objects.get(name='E').pk
+ conflicting = f.is_slug_conflicting('D', ref_node_pk, 'first-child')
+ self.assertEqual(conflicting, False)
+
+ #updating
+ f.instance = Category.objects.get(name='E')
+ ref_node_pk = Category.objects.get(name='A').pk
+ conflicting = f.is_slug_conflicting('E', ref_node_pk, 'first-child')
+ self.assertEqual(conflicting, False)

0 comments on commit 6b4437d

Please sign in to comment.