Django ';具有此电子邮件地址的自定义用户已存在';尝试使用表单更新电子邮件时出错。德扬戈

Django ';具有此电子邮件地址的自定义用户已存在';尝试使用表单更新电子邮件时出错。德扬戈,django,Django,请通读我的代码,我的问题和截图以及我已经尝试过的东西都在我的代码之后 managers.py: from django.contrib.auth.base_user import BaseUserManager from django.utils.translation import ugettext_lazy as _ class CustomUserManager(BaseUserManager): def create_user(self, email, password, *

请通读我的代码,我的问题和截图以及我已经尝试过的东西都在我的代码之后

managers.py:

from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _

class CustomUserManager(BaseUserManager):

    def create_user(self, email, password, **extra_feilds):
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_feilds)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password, **extra_feilds):
        extra_feilds.setdefault('is_staff', True)
        extra_feilds.setdefault('is_superuser', True)
        extra_feilds.setdefault('is_active', True)

        if extra_feilds.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff = True'))
        if extra_feilds.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True'))
        return self.create_user(email, password, **extra_feilds)
models.py:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils.translation import gettext_lazy as _
from .managers import CustomUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), unique=True)
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=40)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    def __str__(self):
        return self.email
forms.py

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser, StripeConnectSetup
from django import forms

class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm):
        model = CustomUser
        fields = ('email', 'first_name', 'last_name')

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('email','first_name', 'last_name')
class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('email','first_name', 'last_name')
    def clean(self):
        pass
views.py

from django.shortcuts import render, redirect
from .forms import CustomUserCreationForm, CustomUserChangeForm, StripeConnectSetupForm
from .models import CustomUser
from django.contrib.auth import login, logout
from django.contrib.auth.forms import AuthenticationForm

def update_user_view(request):
    obj = CustomUser.objects.get(email=request.user.email)
    data = {'email': obj.email, 'first_name': obj.first_name, 'last_name': obj.last_name}
    form = CustomUserChangeForm(initial=data)
    if request.method == 'POST':
        form = CustomUserChangeForm(request.POST, request.FILES)
        if form.is_valid():
            obj = CustomUser.objects.get(email=request.user.email)
            obj.email = form.cleaned_data['email']
            obj.first_name = form.cleaned_data['first_name']
            obj.last_name = form.cleaned_data['last_name']
            obj.save()
            return redirect('accounts:update_user')

    context = {
        'form': form
    }
    return render(request, 'accounts/update_user.html', context)
更新_user.html:

<h1>Update User Profile</h1>
<hr>
<form method="POST" enctype="multipart/form-data"> {% csrf_token %}
    {{form.as_p}}
    <button type="submit" class="btn btn-primary">Update</button>

</form>
这将修复此问题,并允许您在不更新电子邮件的情况下更新您的名字或姓氏

但是,这会导致另一个bug。 当我尝试将电子邮件更改为数据库中已存在的其他电子邮件,而不是获取“此电子邮件地址已存在的自定义用户”错误时,它将加载此屏幕


所以问题是,当我不更新我的电子邮件时,如何阻止“此电子邮件地址已存在的自定义用户”错误,但当我更改我的电子邮件且该电子邮件已存在时,如何允许该错误。

既然要更新对象,只需将关键字参数
实例
传递到表单,而不是传递
首字母
。您会收到错误
“具有此电子邮件地址的自定义用户已存在”
,因为当您编写
CustomUserChangeForm(request.POST,request.FILES)
时,它会尝试验证表单,并将其视为创建新用户,这会给您一个错误

ModelForm
的文档中:

ModelForm的子类可以将现有模型实例作为 关键字参数实例;如果提供了此选项,save() 将更新该实例。如果未提供,则save()将 创建指定模型的新实例

所以你的观点应该是:

def更新用户视图(请求):
obj=CustomUser.objects.get(email=request.user.email)
表单=CustomUserChangeForm(实例=obj)
如果request.method==“POST”:
form=CustomUserChangeForm(request.POST,request.FILES,instance=obj)
如果form.is_有效():
obj=form.save()
返回重定向('帐户:更新\用户')
上下文={
“形式”:形式
}
返回呈现(请求“accounts/update_user.html”,上下文)
接下来,将表单更改回原来的状态,以便
clean
方法保持不变:

类CustomUserChangeForm(UserChangeForm):
类元:
模型=自定义用户
字段=('email'、'first\u name'、'last\u name')