Generate valid slug in wizard if the given one is taken
This commit is contained in:
parent
5ba20ed133
commit
f71f1d0390
4 changed files with 88 additions and 13 deletions
|
@ -8,10 +8,10 @@ from cms.wizards.wizard_base import Wizard
|
||||||
from cms.wizards.wizard_pool import AlreadyRegisteredException, wizard_pool
|
from cms.wizards.wizard_pool import AlreadyRegisteredException, wizard_pool
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.text import slugify
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from .cms_appconfig import BlogConfig
|
from .cms_appconfig import BlogConfig
|
||||||
|
from .fields import slugify
|
||||||
from .forms import PostAdminFormBase
|
from .forms import PostAdminFormBase
|
||||||
from .models import Post
|
from .models import Post
|
||||||
|
|
||||||
|
@ -19,6 +19,11 @@ from .models import Post
|
||||||
class PostWizardForm(PostAdminFormBase):
|
class PostWizardForm(PostAdminFormBase):
|
||||||
default_appconfig = None
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
if 'initial' not in kwargs or not kwargs.get('initial', False):
|
if 'initial' not in kwargs or not kwargs.get('initial', False):
|
||||||
kwargs['initial'] = {}
|
kwargs['initial'] = {}
|
||||||
|
@ -36,7 +41,7 @@ class PostWizardForm(PostAdminFormBase):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Post
|
model = Post
|
||||||
fields = ['app_config', 'title', 'abstract', 'categories']
|
fields = ['app_config', 'title', 'slug', 'abstract', 'categories']
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
js = ('admin/js/jquery.js', 'admin/js/jquery.init.js',)
|
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())
|
self.instance._set_default_author(get_current_user())
|
||||||
return super(PostWizardForm, self).save(commit)
|
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):
|
class PostWizard(Wizard):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -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.db.models import SlugField
|
||||||
|
from django.utils.text import slugify as django_slugify
|
||||||
|
|
||||||
__all__ = ['AutoSlugField']
|
__all__ = ['AutoSlugField']
|
||||||
|
|
||||||
|
@ -7,3 +12,10 @@ class AutoSlugField(SlugField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.allow_unicode = kwargs.pop('allow_unicode', False)
|
self.allow_unicode = kwargs.pop('allow_unicode', False)
|
||||||
super(SlugField, self).__init__(*args, **kwargs)
|
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)
|
||||||
|
|
|
@ -3,7 +3,6 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
import django
|
|
||||||
from aldryn_apphooks_config.fields import AppHookConfigField
|
from aldryn_apphooks_config.fields import AppHookConfigField
|
||||||
from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager
|
from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager
|
||||||
from cms.models import CMSPlugin, PlaceholderField
|
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.encoding import force_bytes, force_text, python_2_unicode_compatible
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.html import escape, strip_tags
|
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 django.utils.translation import get_language, ugettext_lazy as _
|
||||||
from djangocms_text_ckeditor.fields import HTMLField
|
from djangocms_text_ckeditor.fields import HTMLField
|
||||||
from filer.fields.image import FilerImageField
|
from filer.fields.image import FilerImageField
|
||||||
|
@ -30,7 +28,7 @@ from sortedm2m.fields import SortedManyToManyField
|
||||||
from taggit_autosuggest.managers import TaggableManager
|
from taggit_autosuggest.managers import TaggableManager
|
||||||
|
|
||||||
from .cms_appconfig import BlogConfig
|
from .cms_appconfig import BlogConfig
|
||||||
from .fields import AutoSlugField
|
from .fields import AutoSlugField, slugify
|
||||||
from .managers import GenericDateTaggedManager
|
from .managers import GenericDateTaggedManager
|
||||||
from .settings import get_setting
|
from .settings import get_setting
|
||||||
|
|
||||||
|
@ -47,7 +45,6 @@ thumbnail_model = '%s.%s' % (
|
||||||
ThumbnailOption._meta.app_label, ThumbnailOption.__name__
|
ThumbnailOption._meta.app_label, ThumbnailOption.__name__
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from knocker.mixins import KnockerModel
|
from knocker.mixins import KnockerModel
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -315,10 +312,7 @@ class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
|
||||||
if self.publish and self.date_published is None:
|
if self.publish and self.date_published is None:
|
||||||
self.date_published = timezone.now()
|
self.date_published = timezone.now()
|
||||||
if not self.slug and self.title:
|
if not self.slug and self.title:
|
||||||
if django.VERSION >= (1, 9):
|
self.slug = slugify(self.title)
|
||||||
self.slug = slugify(self.title, allow_unicode=True)
|
|
||||||
else:
|
|
||||||
self.slug = slugify(self.title)
|
|
||||||
super(Post, self).save(*args, **kwargs)
|
super(Post, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def save_translation(self, translation, *args, **kwargs):
|
def save_translation(self, translation, *args, **kwargs):
|
||||||
|
@ -349,9 +343,12 @@ class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
|
||||||
if '<day>' in urlconf:
|
if '<day>' in urlconf:
|
||||||
kwargs['day'] = '%02d' % current_date.day
|
kwargs['day'] = '%02d' % current_date.day
|
||||||
if '<slug>' in urlconf:
|
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:
|
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)
|
return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self):
|
||||||
|
@ -555,7 +552,6 @@ class AuthorEntriesPlugin(BasePostPlugin):
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class GenericBlogPlugin(BasePostPlugin):
|
class GenericBlogPlugin(BasePostPlugin):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,51 @@ class WizardTest(BaseTest):
|
||||||
instance = form.save()
|
instance = form.save()
|
||||||
self.assertEqual(instance.author, self.user_normal)
|
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):
|
def test_wizard_init_categories_check(self):
|
||||||
from cms.utils.permissions import current_user
|
from cms.utils.permissions import current_user
|
||||||
from cms.wizards.wizard_pool import wizard_pool
|
from cms.wizards.wizard_pool import wizard_pool
|
||||||
|
|
Loading…
Reference in a new issue