Allow to generate random slugs

This commit is contained in:
Raphael Michel
2017-06-28 18:20:06 +02:00
parent 4bd0b96a2d
commit ea970be6f2
6 changed files with 38 additions and 2 deletions

View File

@@ -67,7 +67,9 @@ class Event(LoggedModel):
max_length=50, db_index=True, max_length=50, db_index=True,
help_text=_( help_text=_(
"Should be short, only contain lowercase letters and numbers, and must be unique among your events. " "Should be short, only contain lowercase letters and numbers, and must be unique among your events. "
"This will be used in order codes, invoice numbers, links and bank transfer references."), "We recommend some kind of abbreviation or a date with less than 10 characters that can be easily "
"remembered, but you can also choose to use a random value. "
"This will be used in URLs, order codes, invoice numbers, and bank transfer references."),
validators=[ validators=[
RegexValidator( RegexValidator(
regex="^[a-zA-Z0-9.-]+$", regex="^[a-zA-Z0-9.-]+$",

View File

@@ -5,7 +5,9 @@
<fieldset> <fieldset>
<legend>{% trans "General information" %}</legend> <legend>{% trans "General information" %}</legend>
{% bootstrap_field form.name layout="horizontal" %} {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.slug layout="horizontal" %} {% trans "Random" as rndlabel %}
{% url "control:events.add.slugrng" organizer=organizer.slug as rngurl %}
{% bootstrap_field form.slug layout="horizontal" addon_after='<button class="btn btn-default" type="button" id="event-slug-random-generate" data-rng-url="'|add:rngurl|add:'">'|add:rndlabel|add:'</button>' addon_after_class='input-group-btn' %}
{% bootstrap_field form.date_from layout="horizontal" %} {% bootstrap_field form.date_from layout="horizontal" %}
{% bootstrap_field form.date_to layout="horizontal" %} {% bootstrap_field form.date_to layout="horizontal" %}
{% bootstrap_field form.location layout="horizontal" %} {% bootstrap_field form.location layout="horizontal" %}

View File

@@ -43,6 +43,7 @@ urlpatterns = [
name='organizer.team.edit'), name='organizer.team.edit'),
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/delete$', organizer.TeamDeleteView.as_view(), url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/delete$', organizer.TeamDeleteView.as_view(),
name='organizer.team.delete'), name='organizer.team.delete'),
url(r'^organizer/(?P<organizer>[^/]+)/slugrng', main.SlugRNG.as_view(), name='events.add.slugrng'),
url(r'^events/$', main.EventList.as_view(), name='events'), url(r'^events/$', main.EventList.as_view(), name='events'),
url(r'^events/add$', main.EventWizard.as_view(), name='events.add'), url(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'), url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),

View File

@@ -2,9 +2,12 @@ from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views import View
from django.views.generic import ListView from django.views.generic import ListView
from formtools.wizard.views import SessionWizardView from formtools.wizard.views import SessionWizardView
@@ -13,6 +16,7 @@ from pretix.control.forms.event import (
EventWizardBasicsForm, EventWizardCopyForm, EventWizardFoundationForm, EventWizardBasicsForm, EventWizardCopyForm, EventWizardFoundationForm,
) )
from pretix.control.forms.filter import EventFilterForm from pretix.control.forms.filter import EventFilterForm
from pretix.control.permissions import OrganizerPermissionRequiredMixin
class EventList(ListView): class EventList(ListView):
@@ -61,6 +65,8 @@ class EventWizard(SessionWizardView):
def get_context_data(self, form, **kwargs): def get_context_data(self, form, **kwargs):
ctx = super().get_context_data(form, **kwargs) ctx = super().get_context_data(form, **kwargs)
ctx['has_organizer'] = self.request.user.teams.filter(can_create_events=True).exists() ctx['has_organizer'] = self.request.user.teams.filter(can_create_events=True).exists()
if self.steps.current == 'basics':
ctx['organizer'] = self.get_cleaned_data_for_step('foundation').get('organizer')
return ctx return ctx
def get_form_kwargs(self, step=None): def get_form_kwargs(self, step=None):
@@ -121,3 +127,16 @@ class EventWizard(SessionWizardView):
'organizer': event.organizer.slug, 'organizer': event.organizer.slug,
'event': event.slug, 'event': event.slug,
})) }))
class SlugRNG(OrganizerPermissionRequiredMixin, View):
def get(self, request, *args, **kwargs):
# See Order.assign_code
charset = list('abcdefghjklmnpqrstuvwxyz3789')
for i in range(100):
val = get_random_string(length=settings.ENTROPY['order_code'], allowed_chars=charset)
if not self.request.organizer.events.filter(slug__iexact=val).exists():
break
return JsonResponse({'slug': val})

View File

@@ -102,6 +102,15 @@ $(function () {
question_page_toggle_view(); question_page_toggle_view();
} }
// Event wizard
$("#event-slug-random-generate").click(function () {
var url = $(this).attr("data-rng-url");
$("#id_basics-slug").val("Generating...");
$.getJSON(url, function (data) {
$("#id_basics-slug").val(data.slug);
});
});
// Vouchers // Vouchers
$("#voucher-bulk-codes-generate").click(function () { $("#voucher-bulk-codes-generate").click(function () {
var num = $("#voucher-bulk-codes-num").val(); var num = $("#voucher-bulk-codes-num").val();

View File

@@ -151,3 +151,6 @@ pre.mail-preview {
width: 1% !important; width: 1% !important;
} }
} }
.input-group-btn .btn {
padding-bottom: 7px;
}