def event_selections_edit_option(request, event_pk, group_pk, option_pk): event = get_object_or_404(Event, pk=event_pk) group = get_object_or_404(event.optiongroups, pk=group_pk) _option = get_object_or_404(group.options, pk=option_pk) type_manager = type_manager_factory(_option) stype_manager = stype_manager_factory(_option) # fetch the correct "overloaded" option option = type_manager.get_model().objects.get(pk=_option.pk) view = stype_manager.get_update_view() return view(request, event, group, instance=option)
def copy_and_mutate_self(self): from selvbetjening.core.events.options.typemanager import type_manager_factory optiongroups = list(self.optiongroup_set.all()) self.pk = None self.title = '%s (copy)' % self.title self.is_visible = False self.save() for group in optiongroups: options = list(group.options) group.pk = None group.save() self.optiongroup_set.add(group) for _option in options: suboptions = list(_option.suboptions) # fetch the correct "overloaded" option type_manager = type_manager_factory(_option) option = type_manager.get_model().objects.get(pk=_option.pk) # copy option in a way that is compatible with inheritance from django.db.models import AutoField fields = dict([(f.name, getattr(option, f.name)) for f in option._meta.fields if not isinstance(f, AutoField) and\ not f in option._meta.parents.values()]) new_obj = option.__class__(**fields) new_obj.pk = None new_obj.save() group.option_set.add(new_obj) for suboption in suboptions: suboption.pk = None suboption.save() new_obj.suboption_set.add(suboption)
def event_selections_delete_option(request, event_pk, group_pk, option_pk): event = get_object_or_404(Event, pk=event_pk) group = get_object_or_404(event.optiongroups, pk=group_pk) _option = get_object_or_404(group.options, pk=option_pk) type_manager = type_manager_factory(_option) # fetch the correct "overloaded" option option = type_manager.get_model().objects.get(pk=_option.pk) context = { "sadmin2_menu_main_active": "events", "sadmin2_breadcrumbs_active": "event_selections_delete_option", "sadmin2_menu_tab": menu.sadmin2_menu_tab_event, "sadmin2_menu_tab_active": "settings", "event": event, "option_group": group, "option": option, } # Check if we are allowed to delete this object selection_count = Selection.objects.filter(option=option).count() if selection_count > 0: context["selection_count"] = selection_count return render(request, "sadmin2/event/selection_option_delete_not_possible.html", context) # If yes, then ... if request.method == "POST": option.delete() messages.success(request, _("Option %s deleted" % option.name)) return HttpResponseRedirect(reverse("sadmin2:event_settings_selections", kwargs={"event_pk": event.pk})) context["obj_type"] = "Option" context["to_be_deleted"] = _get_deleted_objects([option]) return render(request, "sadmin2/generic/delete.html", context)
def dynamic_selections_form_factory(scope, option_group_instance, helper_factory=None, options=None): if options is None: options = dynamic_options(scope, option_group_instance.event, option_group=option_group_instance) options = [option[0] for option in options] # TODO use selections from dynamic options def init(self, *args, **kwargs): self.attendee = kwargs.pop('attendee', None) self.attendee = kwargs.pop('instance', self.attendee) self.user = kwargs.pop('user') if self.attendee is not None: self.user = self.attendee.user # force the usage of attendee.user if self.attendee is not None: initial = {} selections = kwargs.pop('selections', None) if selections is None: selections = self.attendee.selection_set.all().select_related('option') for selection in selections: field_id = _pack_id('option', selection.option.pk) if field_id in self.type_widgets: initial[field_id] = self.type_widgets[field_id].initial_value(selection) kwargs['initial'] = initial super(forms.Form, self).__init__(*args, **kwargs) for field_id, type_widget in self.type_widgets.items(): if hasattr(type_widget, 'update_choices'): type_widget.update_choices(self.user, self.attendee) self.fields[field_id].choices = type_widget.choices if self.attendee is not None and not type_widget.is_editable(self.attendee): self.fields[field_id].widget.attrs['disabled'] = "disabled" def save(self, *args, **kwargs): attendee = kwargs.pop('attendee', self.attendee) assert attendee is not None for key, save_callback in self.save_callbacks.items(): save_callback(attendee, self.cleaned_data.get(key, None)) def clean_callback(field_id, related_field, type_manager_clean_callback): def inner(self): # If we have a related field, then erase the value if the related field is not selected. if related_field is not None: # Related field is readonly and is not set "initially" if related_field in self.readonly and not self.initial.get(related_field, False): return None if related_field not in self.readonly and not self.cleaned_data.get(related_field, False): return None return type_manager_clean_callback(self.cleaned_data.get(field_id, None)) return inner @staticmethod def is_empty(): return len(options) == 0 def clean(self): cleaned_data = super(forms.Form, self).clean() if scope == SCOPE.SADMIN: # Do not enforce max/min for admin return cleaned_data if option_group_instance.minimum_selected <= 0 and option_group_instance.maximum_selected <= 0: return cleaned_data selected = 0 for option in options: field_id = _pack_id('option', option.pk) if getattr(option, scope): # field is editable value = cleaned_data.get(field_id, None) else: value = self.initial.get(field_id, None) selected += 1 if self._selected_callbacks[field_id](value) else 0 if option_group_instance.minimum_selected > 0 and selected < option_group_instance.minimum_selected: raise forms.ValidationError(ungettext_lazy('You must select at least %d option.', 'You must select at least %d options.', option_group_instance.minimum_selected) % option_group_instance.minimum_selected) if 0 < option_group_instance.maximum_selected < selected: raise forms.ValidationError(ungettext_lazy('You must select at most %d option.', 'You must select at most %d options.', option_group_instance.maximum_selected) % option_group_instance.maximum_selected) return cleaned_data fields = { '__init__': init, 'save': save, 'is_empty': is_empty, 'clean': clean, 'save_callbacks': {}, '_selected_callbacks': {}, 'type_widgets': {}, 'readonly': [] } for option in options: widget = type_manager_factory(option).get_widget(scope, option) field_id = _pack_id('option', option.pk) related_field = None attrs = None if option.depends_on is not None: related_field = _pack_id('option', option.depends_on.pk) attrs = {'data-depends-on': related_field} fields[field_id] = widget.get_field(attrs=attrs) fields['_selected_callbacks'][field_id] = widget.selected_callback if scope == SCOPE.SADMIN or getattr(option, scope): # The edit scope bit is set fields['clean_%s' % field_id] = clean_callback(field_id, related_field, widget.clean_callback) fields['save_callbacks'][field_id] = widget.save_callback else: # The edit bit is not set, this is a view only option fields['clean_%s' % field_id] = lambda self: None fields['save_callbacks'][field_id] = lambda attendee, value: None if not hasattr(fields[field_id].widget, 'CANT_DISABLE'): fields[field_id].widget.attrs['disabled'] = 'disabled' fields[field_id].required = False # If we don't do this Django will err because of missing POST data fields['readonly'].append(field_id) fields['type_widgets'][field_id] = widget if helper_factory is not None: fields['helper'] = helper_factory(option_group_instance, [_pack_id('option', option.pk) for option in options]) return type('OptionGroupSelectionsForm', (forms.Form,), fields)