在django-admin内联表单上验证删除

时间:2010-11-29 13:55:05

标签: django validation django-admin django-forms

我正在尝试执行验证,以便在他是管理员时无法删除用户。因此,如果用户是管理员并且已被标记为删除,我想检查并引发错误。

这是我的内联ModelForm

class UserGroupsForm(forms.ModelForm):
    class Meta:
        model = UserGroups

    def clean(self):
        delete_checked = self.fields['DELETE'].widget.value_from_datadict(
            self.data, self.files, self.add_prefix('DELETE'))
        if bool(delete_checked):
            #if user is admin of group x
            raise forms.ValidationError('You cannot delete a user that is the group administrator')

        return self.cleaned_data

if bool(delete_checked):条件返回true并且if块中的内容被执行但由于某种原因,从未引发此验证错误。有人可以向我解释原因吗?

更好的是,如果还有另一种更好的方法,请告诉我

3 个答案:

答案 0 :(得分:7)

我找到的解决方案是clean而不是InlineFormSet

ModelForm
class UserGroupsInlineFormset(forms.models.BaseInlineFormSet):

    def clean(self):
        delete_checked = False

        for form in self.forms:
            try:
                if form.cleaned_data:
                    if form.cleaned_data['DELETE']:
                        delete_checked = True

            except AttributeError:
                pass

        if delete_checked:
            raise forms.ValidationError(u'You cannot delete a user that is the group administrator')

答案 1 :(得分:0)

尽管@domino的答案可能暂时有效,但“ kinda” recommended approach是将formset的self._should_delete_form(form)函数与self.can_delete一起使用。

还有一个调用super().clean()来执行标准内置验证的问题。因此,最终代码可能如下所示:

class UserGroupsInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        super().clean()
        if any(self.errors):
            return  # Don't bother validating the formset unless each form is valid on its own
        for form in self.forms:
            if self.can_delete and self._should_delete_form(form):
                if <...form.instance.is_admin...>:
                    raise ValidationError('...')

答案 2 :(得分:0)

添加到多米诺骨牌的答案中:

在其他情况下,有时用户希望同时删除添加对象,因此在这种情况下,删除应该没问题!

代码的优化版本:

class RequiredImageInlineFormset(forms.models.BaseInlineFormSet):
    """ Makes inline fields required """

    def clean(self):
        # get forms that actually have valid data
        count = 0
        delete_checked = 0
        for form in self.forms:
            try:
                if form.cleaned_data:
                    count += 1
                    if form.cleaned_data['DELETE']:
                        delete_checked += 1
                    if not form.cleaned_data['DELETE']:
                        delete_checked -= 1
            except AttributeError:
                # annoyingly, if a subform is invalid Django explicity raises
                # an AttributeError for cleaned_data
                pass

        # Case no images uploaded
        if count < 1:
            raise forms.ValidationError(
                'At least one image is required.')

        # Case one image added and another deleted
        if delete_checked > 0 and ProductImage.objects.filter(product=self.instance).count() == 1:
            raise forms.ValidationError(
                "At least one image is required.")