diff --git a/requirements.txt b/requirements.txt index f5eaa461..52ae0365 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,7 @@ Markdown==2.4.1 fn==0.2.13 diff-match-patch==20121119 requests==2.4.1 +Unidecode==0.04.16 # Comment it if you are using python >= 3.4 enum34==1.0 diff --git a/taiga/base/utils/slug.py b/taiga/base/utils/slug.py index 14e17abf..c4a389e7 100644 --- a/taiga/base/utils/slug.py +++ b/taiga/base/utils/slug.py @@ -19,6 +19,8 @@ from django.template.defaultfilters import slugify import time +from unidecode import unidecode + def slugify_uniquely(value, model, slugfield="slug"): """ @@ -26,13 +28,13 @@ def slugify_uniquely(value, model, slugfield="slug"): """ suffix = 0 - potential = base = slugify(value) + potential = base = slugify(unidecode(value)) if len(potential) == 0: potential = 'null' while True: if suffix: potential = "-".join([base, str(suffix)]) - if not model.objects.filter(**{slugfield: potential}).count(): + if not model.objects.filter(**{slugfield: potential}).exists(): return potential suffix += 1 diff --git a/taiga/projects/migrations/0004_auto_20141002_2337.py b/taiga/projects/migrations/0004_auto_20141002_2337.py new file mode 100644 index 00000000..14876435 --- /dev/null +++ b/taiga/projects/migrations/0004_auto_20141002_2337.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0003_auto_20140913_1710'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='name', + field=models.CharField(max_length=250, verbose_name='name'), + ), + ] diff --git a/taiga/projects/models.py b/taiga/projects/models.py index ed2adf4a..c8306c46 100644 --- a/taiga/projects/models.py +++ b/taiga/projects/models.py @@ -118,7 +118,7 @@ class ProjectDefaults(models.Model): class Project(ProjectDefaults, TaggedMixin, models.Model): - name = models.CharField(max_length=250, unique=True, null=False, blank=False, + name = models.CharField(max_length=250, null=False, blank=False, verbose_name=_("name")) slug = models.SlugField(max_length=250, unique=True, null=False, blank=True, verbose_name=_("slug")) @@ -189,7 +189,8 @@ class Project(ProjectDefaults, TaggedMixin, models.Model): self.modified_date = timezone.now() if not self.slug: - base_slug = slugify_uniquely(self.name, self.__class__) + base_name = "{}-{}".format(self.owner.username, self.name) + base_slug = slugify_uniquely(base_name, self.__class__) slug = base_slug for i in arithmetic_progression(): if not type(self).objects.filter(slug=slug).exists() or i > 100: diff --git a/tests/unit/test_slug.py b/tests/unit/test_slug.py new file mode 100644 index 00000000..ea7dd17d --- /dev/null +++ b/tests/unit/test_slug.py @@ -0,0 +1,37 @@ +# Copyright (C) 2014 Andrey Antukh +# Copyright (C) 2014 Jesús Espino +# Copyright (C) 2014 David Barragán +# Copyright (C) 2014 Anler Hernández +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from taiga.projects.models import Project +from taiga.users.models import User + +import pytest +pytestmark = pytest.mark.django_db + + +def test_project_slug_with_special_chars(): + user = User.objects.create(username="test") + project = Project.objects.create(name="漢字", description="漢字", owner=user) + project.save() + + assert project.slug == "test-han-zi" + +def test_project_with_existing_name_slug_with_special_chars(): + user = User.objects.create(username="test") + Project.objects.create(name="漢字", description="漢字", owner=user) + project = Project.objects.create(name="漢字", description="漢字", owner=user) + + assert project.slug == "test-han-zi-1"