forked from CGM_Public/pretix_original
Add _none-option to ModelChoiceField and filters for organizer and event-permission in event-typeahead (#6224)
* Add optional filters for organizer and event-permission on event-typeahead * include _none option only if no search query given Co-authored-by: luelista <weller@rami.io> * allow _none in Select2, add ModelChoiceFieldWithNone * fix flake8 --------- Co-authored-by: luelista <weller@rami.io>
This commit is contained in:
committed by
GitHub
parent
375c42dff5
commit
d555b23275
@@ -461,3 +461,31 @@ class SalesChannelCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
|||||||
**super().create_option(name, value, label, selected, index, subindex, attrs),
|
**super().create_option(name, value, label, selected, index, subindex, attrs),
|
||||||
"plugin_missing": plugin and plugin not in self.event.get_plugins(),
|
"plugin_missing": plugin and plugin not in self.event.get_plugins(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ModelChoiceIteratorWithNone(forms.models.ModelChoiceIterator):
|
||||||
|
# see django.forms.models.ModelChoiceIterator for original implementation
|
||||||
|
def __iter__(self):
|
||||||
|
if self.field.empty_label is not None:
|
||||||
|
yield ("", self.field.empty_label)
|
||||||
|
if self.field.none_label is not None:
|
||||||
|
yield ("_none", self.field.none_label)
|
||||||
|
queryset = self.queryset
|
||||||
|
# Can't use iterator() when queryset uses prefetch_related()
|
||||||
|
if not queryset._prefetch_related_lookups:
|
||||||
|
queryset = queryset.iterator()
|
||||||
|
for obj in queryset:
|
||||||
|
yield self.choice(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class ModelChoiceFieldWithNone(forms.ModelChoiceField):
|
||||||
|
iterator = ModelChoiceIteratorWithNone
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.none_label = kwargs.pop("none_label", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
if value == "_none":
|
||||||
|
return value
|
||||||
|
return super().to_python(value)
|
||||||
|
|||||||
@@ -29,17 +29,30 @@ class Select2Mixin:
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def options(self, name, value, attrs=None):
|
def options(self, name, value, attrs=None):
|
||||||
if value and value[0]:
|
if not value or not value[0]:
|
||||||
for i, selected in enumerate(self.choices.queryset.filter(pk__in=value)):
|
return
|
||||||
yield self.create_option(
|
has_none = "_none" in value
|
||||||
None,
|
if has_none:
|
||||||
self.choices.field.prepare_value(selected),
|
value = [v for v in value if v != "_none"]
|
||||||
self.choices.field.label_from_instance(selected),
|
yield self.create_option(
|
||||||
True,
|
None,
|
||||||
i,
|
"_none",
|
||||||
subindex=None,
|
self.choices.field.none_label,
|
||||||
attrs=attrs
|
True,
|
||||||
)
|
0,
|
||||||
|
subindex=None,
|
||||||
|
attrs=attrs
|
||||||
|
)
|
||||||
|
for i, selected in enumerate(self.choices.queryset.filter(pk__in=value)):
|
||||||
|
yield self.create_option(
|
||||||
|
None,
|
||||||
|
self.choices.field.prepare_value(selected),
|
||||||
|
self.choices.field.label_from_instance(selected),
|
||||||
|
True,
|
||||||
|
i + (1 if has_none else 0),
|
||||||
|
subindex=None,
|
||||||
|
attrs=attrs
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
def optgroups(self, name, value, attrs=None):
|
def optgroups(self, name, value, attrs=None):
|
||||||
|
|||||||
@@ -145,11 +145,21 @@ def event_list(request):
|
|||||||
if 'can_copy' in request.GET:
|
if 'can_copy' in request.GET:
|
||||||
qs = EventWizardCopyForm.copy_from_queryset(request.user, request.session)
|
qs = EventWizardCopyForm.copy_from_queryset(request.user, request.session)
|
||||||
else:
|
else:
|
||||||
qs = request.user.get_events_with_any_permission(request)
|
permission = request.GET.get('permission')
|
||||||
|
if permission:
|
||||||
|
qs = request.user.get_events_with_permission(permission, request)
|
||||||
|
else:
|
||||||
|
qs = request.user.get_events_with_any_permission(request)
|
||||||
|
|
||||||
|
name_slug_q = Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query)
|
||||||
|
organizer = request.GET.get('organizer')
|
||||||
|
if organizer:
|
||||||
|
qs = qs.filter(organizer__slug=organizer)
|
||||||
|
else:
|
||||||
|
name_slug_q |= Q(organizer__name__icontains=i18ncomp(query)) | Q(organizer__slug__icontains=query)
|
||||||
|
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query) |
|
name_slug_q
|
||||||
Q(organizer__name__icontains=i18ncomp(query)) | Q(organizer__slug__icontains=query)
|
|
||||||
).annotate(
|
).annotate(
|
||||||
min_from=Min('subevents__date_from'),
|
min_from=Min('subevents__date_from'),
|
||||||
max_from=Max('subevents__date_from'),
|
max_from=Max('subevents__date_from'),
|
||||||
@@ -162,10 +172,19 @@ def event_list(request):
|
|||||||
total = qs.count()
|
total = qs.count()
|
||||||
pagesize = 20
|
pagesize = 20
|
||||||
offset = (page - 1) * pagesize
|
offset = (page - 1) * pagesize
|
||||||
|
results = []
|
||||||
|
if page == 1 and 'include_none' in request.GET and not query:
|
||||||
|
results.append({
|
||||||
|
'id': "_none",
|
||||||
|
'text': _("No event"),
|
||||||
|
'name': _("No event"),
|
||||||
|
'type': "event",
|
||||||
|
})
|
||||||
|
results += [
|
||||||
|
serialize_event(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
||||||
|
]
|
||||||
doc = {
|
doc = {
|
||||||
'results': [
|
'results': results,
|
||||||
serialize_event(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
|
||||||
],
|
|
||||||
'pagination': {
|
'pagination': {
|
||||||
"more": total >= (offset + pagesize)
|
"more": total >= (offset + pagesize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -639,11 +639,13 @@ var form_handlers = function (el) {
|
|||||||
).append(" ").append($("<div>").text(res.organizer).html())
|
).append(" ").append($("<div>").text(res.organizer).html())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$ret.append(
|
if (res.date_range) {
|
||||||
$("<span>").addClass("event-daterange").append(
|
$ret.append(
|
||||||
$("<span>").addClass("fa fa-calendar fa-fw")
|
$("<span>").addClass("event-daterange").append(
|
||||||
).append(" ").append(res.date_range)
|
$("<span>").addClass("fa fa-calendar fa-fw")
|
||||||
);
|
).append(" ").append(res.date_range)
|
||||||
|
);
|
||||||
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
},
|
},
|
||||||
}).on("select2:select", function () {
|
}).on("select2:select", function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user