Merge pull request #418 from nephila/hotfix/slug_clean

Generate valid slug in wizard if the given one is taken
This commit is contained in:
Iacopo Spalletti 2018-01-20 19:43:54 +01:00 committed by GitHub
commit 7cd9294adc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 13 deletions

View file

@ -8,10 +8,10 @@ from cms.wizards.wizard_base import Wizard
from cms.wizards.wizard_pool import AlreadyRegisteredException, wizard_pool
from django import forms
from django.conf import settings
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
from .cms_appconfig import BlogConfig
from .fields import slugify
from .forms import PostAdminFormBase
from .models import Post
@ -19,6 +19,11 @@ from .models import Post
class PostWizardForm(PostAdminFormBase):
default_appconfig = None
slug = forms.SlugField(
label=_('Slug'), max_length=767, required=False,
help_text=_('Leave empty for automatic slug, or override as required.'),
)
def __init__(self, *args, **kwargs):
if 'initial' not in kwargs or not kwargs.get('initial', False):
kwargs['initial'] = {}
@ -36,7 +41,7 @@ class PostWizardForm(PostAdminFormBase):
class Meta:
model = Post
fields = ['app_config', 'title', 'abstract', 'categories']
fields = ['app_config', 'title', 'slug', 'abstract', 'categories']
class Media:
js = ('admin/js/jquery.js', 'admin/js/jquery.init.js',)
@ -45,6 +50,23 @@ class PostWizardForm(PostAdminFormBase):
self.instance._set_default_author(get_current_user())
return super(PostWizardForm, self).save(commit)
def clean_slug(self):
"""
Generate a valid slug, in case the given one is taken
"""
source = self.cleaned_data.get('slug', '')
lang_choice = self.language_code
if not source:
source = slugify(self.cleaned_data.get('title', ''))
qs = Post._default_manager.active_translations(lang_choice).language(lang_choice)
used = list(qs.values_list('translations__slug', flat=True))
slug = source
i = 1
while slug in used:
slug = '%s-%s' % (source, i)
i += 1
return slug
class PostWizard(Wizard):
pass

View file

@ -1,4 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
import django
from django.db.models import SlugField
from django.utils.text import slugify as django_slugify
__all__ = ['AutoSlugField']
@ -7,3 +12,10 @@ class AutoSlugField(SlugField):
def __init__(self, *args, **kwargs):
self.allow_unicode = kwargs.pop('allow_unicode', False)
super(SlugField, self).__init__(*args, **kwargs)
def slugify(base):
if django.VERSION >= (1, 9):
return django_slugify(base, allow_unicode=True)
else:
return django_slugify(base)

View file

@ -3,7 +3,6 @@ from __future__ import absolute_import, print_function, unicode_literals
import hashlib
import django
from aldryn_apphooks_config.fields import AppHookConfigField
from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager
from cms.models import CMSPlugin, PlaceholderField
@ -19,7 +18,6 @@ from django.utils import timezone
from django.utils.encoding import force_bytes, force_text, python_2_unicode_compatible
from django.utils.functional import cached_property
from django.utils.html import escape, strip_tags
from django.utils.text import slugify
from django.utils.translation import get_language, ugettext_lazy as _
from djangocms_text_ckeditor.fields import HTMLField
from filer.fields.image import FilerImageField
@ -30,7 +28,7 @@ from sortedm2m.fields import SortedManyToManyField
from taggit_autosuggest.managers import TaggableManager
from .cms_appconfig import BlogConfig
from .fields import AutoSlugField
from .fields import AutoSlugField, slugify
from .managers import GenericDateTaggedManager
from .settings import get_setting
@ -47,7 +45,6 @@ thumbnail_model = '%s.%s' % (
ThumbnailOption._meta.app_label, ThumbnailOption.__name__
)
try:
from knocker.mixins import KnockerModel
except ImportError:
@ -315,10 +312,7 @@ class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
if self.publish and self.date_published is None:
self.date_published = timezone.now()
if not self.slug and self.title:
if django.VERSION >= (1, 9):
self.slug = slugify(self.title, allow_unicode=True)
else:
self.slug = slugify(self.title)
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def save_translation(self, translation, *args, **kwargs):
@ -349,9 +343,12 @@ class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
if '<day>' in urlconf:
kwargs['day'] = '%02d' % current_date.day
if '<slug>' in urlconf:
kwargs['slug'] = self.safe_translation_getter('slug', language_code=lang, any_language=True) # NOQA
kwargs['slug'] = self.safe_translation_getter(
'slug', language_code=lang, any_language=True
) # NOQA
if '<category>' in urlconf:
kwargs['category'] = category.safe_translation_getter('slug', language_code=lang, any_language=True) # NOQA
kwargs['category'] = category.safe_translation_getter(
'slug', language_code=lang, any_language=True) # NOQA
return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)
def get_title(self):
@ -555,7 +552,6 @@ class AuthorEntriesPlugin(BasePostPlugin):
@python_2_unicode_compatible
class GenericBlogPlugin(BasePostPlugin):
class Meta:
abstract = False

View file

@ -82,6 +82,51 @@ class WizardTest(BaseTest):
instance = form.save()
self.assertEqual(instance.author, self.user_normal)
def test_wizard_duplicate_slug(self):
from cms.utils.permissions import current_user
from cms.wizards.wizard_pool import wizard_pool
from djangocms_blog.models import Post
self.get_pages()
cat_2 = BlogCategory.objects.create(name='category 1 - blog 2', app_config=self.app_config_2)
with current_user(self.user_staff):
wiz = None
for wiz in wizard_pool.get_entries():
if wiz.model == Post and wiz.title == 'New Blog':
break
form = wiz.form(data={
'1-title': 'title article',
'1-abstract': 'abstract article',
'1-categories': [self.category_1.pk],
}, prefix=1)
self.assertEqual(form.default_appconfig, self.app_config_1.pk)
self.assertTrue(form.is_valid())
instance1 = form.save()
self.assertEqual(instance1.slug, 'title-article')
form = wiz.form(data={
'1-title': 'title article',
'1-abstract': 'abstract article',
'1-categories': [self.category_1.pk],
}, prefix=1)
self.assertEqual(form.default_appconfig, self.app_config_1.pk)
self.assertTrue(form.is_valid())
instance2 = form.save()
self.assertEqual(instance2.slug, 'title-article-1')
for wiz in wizard_pool.get_entries():
if wiz.model == Post and wiz.title == 'New Article':
break
form = wiz.form(data={
'1-title': 'title article',
'1-abstract': 'abstract article',
'1-categories': [cat_2.pk],
}, prefix=1)
self.assertEqual(form.default_appconfig, self.app_config_2.pk)
self.assertTrue(form.is_valid())
instance3 = form.save()
self.assertEqual(instance3.slug, 'title-article-2')
def test_wizard_init_categories_check(self):
from cms.utils.permissions import current_user
from cms.wizards.wizard_pool import wizard_pool