【问题标题】:Django: UpdateView with unique fieldDjango:具有唯一字段的 UpdateView
【发布时间】:2014-02-06 17:33:50
【问题描述】:

我正在尝试为我的自定义用户模型创建更新配置文件页面。在我的模型中,我的电子邮件字段设置为唯一的。

class User(UserBase):
     ...
     email = models.EmailField(
            max_length=100,
            unique=True,
            blank=True,
            verbose_name='email address',
        )

那么在我看来我有:

class UpdateProfileView(LoginRequiredMixin, UpdateView):
    template_name = 'accounts/update-profile.html'
    form_class = UpdateProfileForm
    model = User

UpdateProfileForm 唯一要做的就是在clean 方法中检查旧密码与新密码是否不同。

我的问题是当我保存表单时收到错误消息User with this Email address already exists.。既然它是一个更新视图并保存一个没有改变的唯一字段,它不应该不会抛出这个错误吗?如果这是正确的行为,那么如何保存表单并在未更改的情况下忽略电子邮件地址。

提前感谢您的帮助。

【问题讨论】:

  • 我是不是在吃疯狂的药,这不是问题还是愚蠢的问题?
  • 没有人对此有任何反馈?
  • 你为什么不给我们看UpdateProfileForm,这样我们才能得到更好的主意。
  • 右来自form.save docs:“ModelForm 的子类可以接受现有模型实例作为关键字参数实例;如果提供,save() 将更新该实例。如果它是未提供,save() 将创建指定模型的新实例。”你在使用instance 参数吗?
  • 注释掉form_class是否有效?

标签: python django


【解决方案1】:

从您的用户模型定义中删除 blank=True。默认情况下,字段定义为null=False,此外,您还指定该字段必须是唯一的——这是一个重要的字段——因此您不希望表单验证允许空白值。这是关于这些属性的 Django documentationblank 完全是一个表单验证的东西。仅此一项就可以解决错误。

除非您有自定义表单逻辑/验证,否则您不需要 UpdateProfileView 上的 form_class 属性。来自docs:“这些通用视图将自动创建一个 ModelForm”。 (甚至还有一个 UpdateView 示例)。

查看视图在没有form_class 的情况下是否有效,如果有效,则检查您的UpdateProfileForm 代码。

【讨论】:

    【解决方案2】:

    以下是一些建议/替代方案:

    1. 如果您停止使用通用视图(即 UpdateProfileView),您可以在逻辑视图中执行以下步骤:如果请求是 POST,则从表单中获取数据并更新您的模型 (How to update fields in a model without creating a new record in django? )

    2. 为什么不改用 ModelForm? https://docs.djangoproject.com/en/dev/topics/forms/modelforms/

    3. 为什么不与来自 d​​jango.contrib.auth.models 的用户合作? https://docs.djangoproject.com/en/dev/topics/auth/default/#user-objects

    4. 最后,您是否考虑过使用这个已经构建好的 Django 注册应用程序? http://www.michelepasin.org/blog/2011/01/14/setting-up-django-registration/

    【讨论】:

      【解决方案3】:
      1. 永远不要使用blank=True和unique=True,这毫无意义。如果您想让该字段在表单中不需要,只需执行即可。

        class Form(forms.Form):
             ...
        
             def __init__(self, *args, **kwargs):
                  super().__init__(*args, **kwargs)
                  self.fields['unique_field].required = False 
        
      2. 除了前面的答案,当你使用空白=真和唯一=真时,“已经退出 ... blah bla”它的正确行为,因为形式接受空字符串作为值并且它已经存在。你需要重写 clean_field 方法:

        class Form(forms.Form):
            ...
        
            def clean_unique_id(self):
                """
                Take new value or if its '' e.g. None take initial value 
                """
                return self.data['unique_id'] or self.initial['unique_id']
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-06
        • 1970-01-01
        • 2018-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-03
        • 2019-11-23
        相关资源
        最近更新 更多