【问题标题】:Django saving overriden user fails when ModelForm.save is done running当 ModelForm.save 完成运行时,Django 保存覆盖用户失败
【发布时间】:2021-09-07 19:56:34
【问题描述】:

上下文

我重写 AbstractBaseUser 以便为其提供我需要的额外字段。我可以创建一个用户没有问题,我可以使用我的用户对象连接到我的应用程序。当我尝试从管理员视图修改现有用户时,我的问题就开始了。

在我的 User 模型的管理视图中,我显示了与我的用户相关的 Permission 模型的内联,并使用了特定于我的模型的 ModelForm 的覆盖。这是它的代码:

from django.contrib.auth import get_user_model

class CustomUserAdminForm(forms.ModelForm):
    """
    Comment
    """
    class Meta:
        model = User
        fields = [
            "email",
            "password",
            "is_admin"
        ]

    def save(self, commit=True):
        """
        Save override.
        """
        # Raise in case of errors.
        if self.errors:
            raise ValueError(
                "The %s could not be %s because the data didn't validate." % (
                    self.instance._meta.object_name,
                    "created" if self.instance._state.adding else "changed",
                )
            )

        # Get custom User model.
        my_user_model = get_user_model()

        # Find user if the object exists.
        try:
            self.instance = my_user_model.objects.get(email=self.cleaned_data["email"])
        except my_user_model.DoesNotExist:
            self.instance = my_user_model()

        self.instance.email = self.cleaned_data["email"]
        self.instance.is_admin = self.cleaned_data["is_admin"]

        # Saving the hash of the password.
        if not self.cleaned_data["password"].startswith("pbkdf2_sha256$"):
            self.instance.set_password(self.cleaned_data["password"])

        if commit:
            # Copied from BaseModelForm.
            # https://github.com/django/django/blob/master/django/forms/models.py
            # If committing, save the instance and the m2m data immediately.
            self.instance.save()
            self._save_m2m()

        else :
            # If not committing, add a method to the form to allow deferred
            # saving of m2m data.
            self.save_m2m = self._save_m2m

        return self.instance

会发生什么

当我从管理页面(修改电子邮件后)单击“保存”时,我被重定向到更改页面,并显示错误消息“更正错误”,但没有突出显示任何字段。此外,我的 many_to_many 字段被清除。

我尝试了什么

我添加了一些打印以了解表单保存方法是否已运行。看起来它确实运行并完成了,commit == False,所以这不是问题所在。

我尝试通过删除 commit 字段来简化事情,但它创建了另一个用户而不是修改现有用户。使用我上面发布的代码,重定向不会创建新对象,但会丢失 many_to_many 关系。

我尝试将 permission_set 添加到我的表单的 Meta 类中,但它引发了 FieldError。

问题

错误可能来自哪里?

【问题讨论】:

    标签: django django-models django-forms django-admin


    【解决方案1】:

    阅读this answer 我更改了我的表单,使其继承自 django.contrib.auth.forms.UserChangeForm 而不是 django.forms.ModelForm

    另外,我在尝试获取现有对象时犯了一个错误。

    我用过

    try:
        self.instance = my_user_model.objects.get(email=self.cleaned_data["email"])
    except my_user_model.DoesNotExist:
            self.instance = my_user_model()
    

    而不是

    try:
        self.instance = my_user_model.objects.get(email=self.initial["email"])
    except my_user_model.DoesNotExist:
        self.instance = my_user_model()
    

    这解释了为什么它每次都创建一个新对象。

    这两个修改解决了我的问题。

    我不知道这是否可以帮助任何人,如果您认为我应该删除它,请通知我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 2016-03-17
      • 2018-10-07
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      相关资源
      最近更新 更多