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

发布于 2024-10-05 04:14:40 字数 723 浏览 4 评论 0原文

我正在尝试执行验证,以便您无法删除用户(如果他是管理员)。因此,我想检查是否存在管理员用户并已被标记为删除,并提出错误。

这是我的内联 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 块内的内容被执行,但由于某种原因此验证永远不会引发错误。有人可以向我解释一下为什么吗?

更好的是,如果有其他更好的方法来做到这一点,请告诉我

I am trying to perform a validation such that you cannot delete a user if he's an admin. I'd therefore like to check and raise an error if there's a user who's an admin and has been marked for deletion.

This is my inline 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

The if bool(delete_checked): condition returns true and stuff inside the if block gets executed but for some reason this validation error is never raised. Could someone please explain to me why?

Better yet if there's another better way to do this please let me know

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请爱~陌生人 2024-10-12 04:14:40

我找到的解决方案是在 InlineFormSet 而不是 ModelForm 中进行 clean

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')

The solution I found was to clean in the InlineFormSet instead of the 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')
零度° 2024-10-12 04:14:40

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

在其他一些场景中,有时用户希望同时删除添加对象,所以在这种情况下删除应该没问题!

优化版本代码:

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.")

Adding to domino's Answer:

In some other scenarios, Sometimes user wants to delete and add object in the same time, so in this case delete should be fine!

Optimized version of code:

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.")
美羊羊 2024-10-12 04:14:40

虽然@domino的答案目前可能有效,但“有点” 推荐的方法是将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('...')

Although @domino's answer may work for now, the "kinda" recommended approach is to use formset's self._should_delete_form(form) function together with self.can_delete.

There's also the issue of calling super().clean() to perform standard builtin validation. So the final code may look like:

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('...')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文