我是Django的新手,这是我第一次使用该框架创建Web应用程序。我的Web应用程序有3种用户类型:客户,主管和承包商。这三个用户通过称为“用户”的OneToOneField连接到自定义用户模型。 (我的自定义用户模型子类AbstractAbstractUser) 我已经创建了数据库表并运行迁移,完成了所有初始的工作,等等,但是当我尝试为我的Web应用程序创建Client用户(该子类将models.Model子类化)时,出现以下AttributeError:'Client对象没有属性“ set_password”。
我看过一些解决方案,它们建议定义自己的set_password属性(因为models.Model没有这样的属性),或者子类化AbstractBaseUser。我想尝试第一种方法,但是,对于如何为模型定义'set_password'属性,我有些困惑。 附注:请随时指出我的代码中的其他任何错误。
models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser, AbstractBaseUser
from django_countries.fields import CountryField
from django.contrib.auth.base_user import BaseUserManager
from myproject import settings
# Create your models here.
class UserAccountManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Email must be set!')
user = self.model(email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email, password)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using = self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=150, unique=True)
is_client = models.BooleanField(default=False)
is_contractor = models.BooleanField(default=False)
is_supervisor = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
username = models.CharField(max_length=150, blank=True)
is_superuser = True
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserAccountManager()
def has_perm(self, perm, obj=None):
return self.is_superuser
def has_module_perms(self, users):
return self.is_superuser
class Client(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
name = models.CharField(max_length=150, verbose_name='Name')
address_1 = models.CharField(max_length=150, verbose_name='Address')
address_2 = models.CharField(max_length=150, blank=True, verbose_name='Address (#2)')
country = CountryField()
region = models.CharField(max_length=150, blank=True, verbose_name='Region')
city = models.CharField(max_length=150, verbose_name='City')
postal_code = models.CharField(max_length=150, verbose_name='Postal code')
po_box_no = models.IntegerField(blank=True, verbose_name='P.O. Box no')
landline_no = models.IntegerField(verbose_name='Landline number')
mobile_no_1 = models.IntegerField(verbose_name='Mobile number')
mobile_no_2 = models.IntegerField(blank=True, verbose_name='Mobile number (#2)')
bank_name_1 = models.CharField(max_length=150, verbose_name="Bank name")
bank_account_no_1 = models.CharField(max_length=150, verbose_name='Bank account number')
bank_name_2 = models.CharField(max_length=150, blank=True, verbose_name="Bank name (#2)")
bank_account_no_2 = models.CharField(max_length=150, blank=True, verbose_name = 'Bank account number (#2)')
email = models.EmailField(max_length=150, unique=True, verbose_name = 'E-mail')
username = models.CharField(max_length=150, blank=True)
national_id = models.IntegerField(verbose_name='National I.D.')
zip_code = models.IntegerField(verbose_name='ZIP Code', blank=True, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'address_1', 'country', 'city', 'region', 'postal_code',
'po_box_no', 'landline_no', 'mobile_no_1', 'email',
'bank_name_1', 'bank_account_no_1', 'national_id', 'zip_code',
]
def __str__(self):
return self.email
class Meta:
verbose_name = 'client'
verbose_name_plural = 'clients'
def save(self, *args, **kwargs):
if not self.pk:
try:
p = Client.objects.get(email=self.email)
self.pk=p.pk
except Client.DoesNotExist:
pass
super(Client, self).save(*args, **kwargs)
views.py:
from django.shortcuts import render
# Create your views here.
from django.contrib.auth import login
from django.shortcuts import redirect
from django.views.generic import CreateView
from .forms import ClientSignUp, ContractorSignUp, SupervisorSignUp
from .models import Client, Contractor, Supervisor
from decorators import *
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
##@method_decorator([login_required, client_required], name='dispatch')
class ClientSignUpView(CreateView):
model = Client
form_class = ClientSignUp
template_name = 'registration/signup_form.html'
def get_context_data(self, **kwargs):
kwargs['user_type'] = 'client'
return super().get_context_data(**kwargs)
def form_valid(self, form):
user = form.save()
user.save()
login(self.request, user)
return redirect('accounts/profile')
forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import Client, Contractor, Supervisor
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.forms import EmailField
from django.utils.translation import ugettext_lazy as _
import logging
log = logging.getLogger(__name__)
from django.utils.encoding import force_text
from django.db import transaction
# -----------------------------------
# CLIENT SIGNUP FORM
class ClientSignUp(UserCreationForm):
email = EmailField(label=_("Email address"), required=True)
class Meta(UserCreationForm):
model = Client
fields = ('email', 'name', 'address_1', 'address_2', 'country', 'city', 'region', 'postal_code',
'po_box_no', 'landline_no', 'username', 'mobile_no_1', 'mobile_no_2',
'bank_name_1', 'bank_account_no_1', 'bank_name_2', 'bank_account_no_2', 'national_id', 'zip_code',
)
@transaction.atomic
def save(self, commit=True):
user = super().save(commit=False)
user.is_client = True
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user