def clean_username(self): """Username must be unique.""" username = self.cleaned_data['username'] username_taken = User.object.filter(username=username).exist if username_taken: raise forms.all_valid('Username is already in use') return username
def post(self, request, *args, **kwargs): modelform = self.get_modelform() inlines_formsets = self.get_inlines_formsets() if modelform.is_valid(): formsets = [formset for inline, formset in inlines_formsets] if forms.all_valid(formsets): return self.form_valid(modelform, formsets) return self.form_invalid(modelform, inlines_formsets)
def post(self, request, *args, **kwargs): self.object = self.get_object() form_class = self.get_form_class() form = self.get_form(form_class) inlines = self.get_inlines() if form.is_valid() and all_valid(inline.formset for inline in inlines): return self.form_valid(form, inlines) return self.form_invalid(form, inlines)
def post(self, request, *args, **kwargs): self.object = None form_class = self.get_form_class() form = self.get_form(form_class) if form.is_valid(): # we have to make sure that the same instance is used for form and inlines inlines = self.get_inlines(object=form.save(commit=False)) else: inlines = self.get_inlines() if all_valid(inline.formset for inline in inlines) and form.is_valid(): return self.form_valid(form, inlines) return self.form_invalid(form, inlines)
def log_form_addition_or_change(self, form, was_adding, formsets=None): """ Shortcut for logging the addition/deletion made via form. Resembles ModelAdmin too. If there are accompanyed formset to the main action, their change could be logged too. """ if not form.is_valid(): raise ValidationError("Form invalid.") if formsets and not all_valid(formsets): raise ValidationError("Some of the formsets not valid.") message_list = construct_change_message(form, formsets, was_adding) if was_adding: self.log_addition(form.instance, message_list) else: self.log_change(form.instance, message_list)
def is_valid(self, check_forms: typing.Dict[CheckId, "typing.Type[BaseCheckForm]"]) -> bool: # type: ignore if not super().is_valid(): return False checks = self.cleaned_data.get("checks", {}) rforms = { name: check_forms[name](data=value) for name, value in checks.items() if name in check_forms } if forms.all_valid(rforms.values()): # type: ignore self.cleaned_data["checks"] = { name: f.cleaned_data for name, f in rforms.items() } return True self.errors["checks"] = {name: form.errors for name, form in rforms.items()} return False
def article_form(request): context = {} if request.method == 'POST': article = ArticleForm(request.POST) picture_forms = Pictureformset(request.POST, request.FILES) article_instance = "" if article.is_valid(): article_instance = article.save() if all_valid(picture_forms): for pictureform in picture_forms: picture = pictureform.save(commit=False) picture.article = article_instance picture.save() context["form"] = ArticleForm() context["formset"] = Pictureformset() return render(request, "article_form.html", context)
def _changeform_view(self, request, object_id, form_url, extra_context): """ A copy of original django method with 4 tricks 1. Calls whole_changeform_validation 2. Calls pre_save() before saving 3. Calls post_save() after saving 4. emits the signal changeform_saved signal :param request: :param object_id: :param form_url: :param extra_context: :return: """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid( formsets ) and form_validated and self.whole_changeform_validation( request, form, formsets, not add): self.pre_save(form, formsets, change=not add) self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) self.post_save(request, new_object, form, formsets, not add) changeform_saved.send(self.model, instance=new_object, created=add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets( self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _changeform_view(self, request, object_id, form_url, extra_context): # noqa """ Based on https://github.com/django/django/blob/2.2.17/django/contrib/admin/options.py#L1531 The creation of the materialized view needed to happen on background """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( f"The field {to_field} cannot be referenced.") opts = self.model._meta if request.method == "POST" and "_saveasnew" in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if request.method == "POST": if not self.has_change_permission(request, obj): raise PermissionDenied else: if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == "POST": obj_dict = obj.to_dict() if obj else None form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.background_task = create_materialized_view.delay( request.user.pk, obj_dict, serializers.serialize("json", [new_object]), self.construct_change_message(request, form, formsets, add), ) if add: return self.response_add(request, new_object) return self.response_change(request, new_object) else: if add: form = ModelForm( initial=self.get_changeform_initial_data(request)) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets( self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self, ) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _("Add %s") elif self.has_change_permission(request, obj): title = _("Change %s") else: title = _("View %s") context = { **self.admin_site.each_context(request), "title": title % opts.verbose_name, "adminform": adminForm, "object_id": object_id, "original": obj, "is_popup": IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, "to_field": to_field, "media": media, "inline_admin_formsets": inline_formsets, "errors": helpers.AdminErrorList(form, formsets), "preserved_filters": self.get_preserved_filters(request), "show_save_and_continue": False, } context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def is_valid(self): is_valid = super(AdditionalFormsMixin, self).is_valid() if len(self.extra_forms) > 0: return is_valid and all_valid(self.extra_forms) else: return is_valid
def _changeform_view(self, request, object_id, form_url, extra_context): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() # on save if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) # on update if all_valid(formsets) and form_validated: try: # must not fail when there's an error getting the old object old_object = new_object.__class__.objects.get(pk=new_object.pk) except Exception: pass self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message(request, form, formsets, add) if len(change_message) > 0: changes = change_message[0].get('changed') if changes: changes['old_values'] = [] changes['new_values'] = [] changed_fields = changes['fields'] for changed_field in changed_fields: try: # when we failed to get the old object or there's an error, silently continue old = getattr(old_object, changed_field) new = getattr(new_object, changed_field) changes['old_values'].append(str(old)) changes['new_values'].append(str(new)) except Exception: pass if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets(request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets(self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): contents = None to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) contents = [] all_content_forms_valid = True if obj and obj.contents: for content in obj.contents.all(): content = content.polymorph() content.build_admin_form(request.POST, request.FILES) if not content.is_admin_form_valid(): all_content_forms_valid = False contents.append(content) if form.is_valid() and all_content_forms_valid: form_validated = True new_object = self.save_form(request, form, change=not add) for content in contents: content.save_admin_form(request) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: all_content_forms_valid = True if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) contents = [] if obj.contents: for content in obj.contents.all(): content = content.polymorph() content.build_admin_form() contents.append(content) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets) or not all_content_forms_valid, preserved_filters=self.get_preserved_filters(request), contents=contents, copy_url_name='admin:' + self.model._meta.model_name + '_copy', copy_supported=hasattr(obj, 'copy'), change_form_extend_template=self.change_form_extend_template, show_xprez_toolbar=self._show_xprez_toolbar(request, object_id)) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)