Skip to content

Allow users to change version slug #6204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
2 changes: 1 addition & 1 deletion docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ you can request the change sending an email to [email protected].
How do I change the version slug of my project?
-----------------------------------------------

One way is renaming the branch/tag of your version.
You can achieve this by renaming the branch/tag of your version.
But if that isn't possible,
you can rename the slug from the :guilabel:`Versions` tab.

Expand Down
17 changes: 12 additions & 5 deletions readthedocs/builds/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['slug'].help_text = 'Warning: changing the slug will break existing URLs'
self.fields['slug'].help_text = _('The name of the version that you can see on your project\'s URL.')

if self.instance.pk and self.instance.machine:
self.fields['slug'].disabled = True
Expand All @@ -33,10 +33,17 @@ def clean_slug(self):
)
original_slug = self.cleaned_data.get('slug')

slug = slugifier.slugify(original_slug, check_pattern=False)
if not slugifier.is_valid(slug):
msg = _('The slug "{slug}" is not valid.')
raise forms.ValidationError(msg.format(slug=original_slug))
slug = slugifier.slugify(original_slug)
if not slug:
ok_chars = ', '.join(VERSION_OK_CHARS)
msg = _(
'The slug "{slug}" is not valid. '
'It should only contain letters, numbers or {ok_chars}. '
'And can not start with {ok_chars}.'
)
raise forms.ValidationError(
msg.format(slug=original_slug, ok_chars=ok_chars)
)

duplicated = (
Version.objects
Expand Down
22 changes: 12 additions & 10 deletions readthedocs/builds/version_slug.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ def _normalize(self, content):
def is_valid(self, content):
return self.test_pattern.match(content)

def slugify(self, content, check_pattern=True):
def slugify(self, content):
"""
Make ``content`` a valid slug.

It uses ``unicode-slugify`` behind the scenes which works properly with
Unicode characters.

If `check_pattern` is `True`, it checks that the final slug is valid.
:returns: `None` if isn't possible to generate a valid slug.
"""
if not content:
return ''
return None

normalized = self._normalize(content)
slug = unicode_slugify(
Expand All @@ -109,8 +109,8 @@ def slugify(self, content, check_pattern=True):
slug = slug.lstrip(self.ok_chars)
slug = slug or self.fallback_slug

if check_pattern and not self.is_valid(slug):
raise Exception(f'Invalid generated slug: {slug}')
if not self.is_valid(slug):
return None
return slug


Expand Down Expand Up @@ -183,11 +183,12 @@ def create_slug(self, model_instance):
# get fields to populate from and slug field to set
slug_field = model_instance._meta.get_field(self.attname)

slug = slugifier.slugify(
content=getattr(model_instance, self._populate_from),
check_pattern=False,
)
count = 0
content = getattr(model_instance, self._populate_from)
slug = slugifier.slugify(content=content)
if slug is None:
# If we weren't able to generate a valid slug based on the name
# we can still generate one with a suffix.
slug = ''

# strip slug depending on max_length attribute of the slug field
# and clean-up
Expand All @@ -212,6 +213,7 @@ def create_slug(self, model_instance):

# increases the number while searching for the next valid slug
# depending on the given slug, clean-up
count = 0
while not slug or queryset.filter(**kwargs).exists():
slug = original_slug
end = self.uniquifying_suffix(count)
Expand Down
10 changes: 9 additions & 1 deletion readthedocs/templates/projects/project_version_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{% block content-header %}<h1>{% blocktrans with version.name as version_name %}{{ version_name }}{% endblocktrans %}</h1>{% endblock %}

{% block content %}
<h2> Editing {{ version.slug }} </h2>
<h2> Editing {{ version.verbose_name }} </h2>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this so the user can see the original name of the version. They already see the slug now.


{% if request.user|is_admin:project %}
{% if not version.active and version.built %}
Expand All @@ -31,6 +31,14 @@ <h2> Editing {{ version.slug }} </h2>


<form method="post" action=".">
<p class="empty">
{% url 'projects_redirects' project.slug as redirects_url %}
{% blocktrans with redirects_url=redirects_url current_slug=version.slug %}
<strong>Warning!</strong> Changing the slug will break existing URLs.
If you change it, you may want to <a href="{{ redirects_url }}">create an exact redirect</a>
from <span>/en/{{ current_slug }}/$rest</span> to <span>/en/new-slug/</span>.
{% endblocktrans %}
</p>
{% csrf_token %}
{{ form.as_p }}
<p>
Expand Down