Commits

Andy Mikhailenko committed 59d4caf Merge

Merged in aaronvanderlip/django-autoslug (pull request #2)

Comments (0)

Files changed (4)

 * Remco Wendt
 * Johan Charpentier
 * Nicolás Echániz
+* Aaron VanDerlip
 * Your Name Here ;)

autoslug/fields.py

         # (ex. usage: user profile models)
         slug = AutoSlugField(populate_from=lambda instance: instance.user.get_full_name())
 
+        # specifiy model manager for looking up slugs shared by subclasses
+
+        class Article(models.Model):
+            '''An article with title, date and slug. The slug is not totally
+            unique but there will be no two articles with the same slug within
+            any month.
+            '''
+            objects = models.Manager()
+            title = models.CharField(max_length=200)
+            slug = AutoSlugField(populate_from='title', unique_with='pub_date__month', manager=objects)
+
+        class NewsArticle(Article):
+            pass
+
         # autoslugify value using custom `slugify` function
         from autoslug.settings import slugify as default_slugify
         def custom_slugify(value):
         if 'db_index' not in kwargs:
             kwargs['db_index'] = True
 
+        # When using model inheritence, set manager to search for matching
+        # slug values
+        self.manager = kwargs.pop('manager', None)
+
         self.always_update = kwargs.pop('always_update', False)
         super(SlugField, self).__init__(*args, **kwargs)
 
         # get currently entered slug
         value = self.value_from_object(instance)
 
+        manager = self.manager
+
         # autopopulate
         if self.always_update or (self.populate_from and not value):
             value = utils.get_prepopulated_value(self, instance)
 
         # ensure the slug is unique (if required)
         if self.unique or self.unique_with:
-            slug = utils.generate_unique_slug(self, instance, slug)
+            slug = utils.generate_unique_slug(self, instance, slug, manager)
 
         assert slug, 'value is filled before saving'
 

autoslug/tests.py

 import datetime
 
 # django
-from django.db.models import Model, CharField, DateField, ForeignKey
+from django.db.models import Model, CharField, DateField, ForeignKey, Manager
 
 # this app
 from autoslug.settings import slugify as default_slugify
     """
     name = CharField(max_length=200)
     slug = AutoSlugField(populate_from='name', always_update=True)
+
+
+class ModelWithSlugSpaceSharedIntegrityError(ModelWithUniqueSlug):
+    """
+    >>> a = ModelWithUniqueSlug(name='My name')
+    >>> a.save()
+    >>> b = ModelWithSlugSpaceSharedIntegrityError(name='My name')
+    >>> b.save()
+    Traceback (most recent call last):
+    ...
+    IntegrityError: column slug is not unique
+    """
+
+
+class SharedSlugSpace(Model):
+    objects = Manager()
+    name = CharField(max_length=200)
+    # ensure that any subclasses use the base model's manager for testing
+    # slug uniqueness
+    slug = AutoSlugField(populate_from='name', unique=True, manager=objects)
+
+
+class ModelWithSlugSpaceShared(SharedSlugSpace):
+    """
+    >>> a = SharedSlugSpace(name='My name')
+    >>> a.save()
+    >>> a.slug
+    u'my-name'
+    >>> b = ModelWithSlugSpaceShared(name='My name')
+    >>> b.save()
+    >>> b.slug
+    u'my-name-2'
+    """

autoslug/utils.py

         attr = getattr(instance, field.populate_from)
         return callable(attr) and attr() or attr
 
-def generate_unique_slug(field, instance, slug):
+def generate_unique_slug(field, instance, slug, manager):
     """
     Generates unique slug by adding a number to given value until no model
     instance can be found with such slug. If ``unique_with`` (a tuple of field
 
     index = 1
 
+    if not manager:
+        manager = type(instance).objects
+
+
     # keep changing the slug until it is unique
     while True:
         # find instances with same slug
         lookups = dict(default_lookups, **{field.name: slug})
-        rivals = type(instance).objects.filter(**lookups).exclude(pk=instance.pk)
+        rivals = manager.filter(**lookups).exclude(pk=instance.pk)
 
         if not rivals:
             # the slug is unique, no model uses it