我对Django比较陌生。 我有一个Web应用程序(正在开发中),该应用程序使用名为User的自定义用户模型,然后由3个子类继承:Contractor,Supervisor和Client,它提供了3种用户类型。 我可以很好地创建所有三种类型的用户,也可以使用管理站点来查看/编辑/删除它们。 然而。当我尝试使用各自的凭据分别作为客户端和主管登录时,收到错误的电子邮件/密码错误。奇怪的是,当我使用承包商的电子邮件/密码登录时,不会发生此错误。 我无法真正弄清问题是什么,因此无法真正解决问题。如果有人可以指出我必须犯的错误,那就太好了。
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(User):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, parent_link=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)', null=True)
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', null=True)
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)', null=True)
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)", null=True)
bank_account_no_2 = models.CharField(max_length=150, blank=True, verbose_name = 'Bank account number (#2)', null=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', 'postal_code', 'landline_no', 'username',
'mobile_no_1', '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'
class Contractor(User):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, parent_link=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)', null=True)
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', null=True)
landline_no = models.IntegerField(verbose_name='Work phone number')
mobile_no_1 = models.IntegerField(verbose_name='Mobile number')
mobile_no_2 = models.IntegerField(blank=True, verbose_name='Mobile number (#2)', null=True)
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)", null=True)
bank_account_no_2 = models.CharField(max_length=150, blank=True, verbose_name = 'Bank account number (#2)', null=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', 'postal_code', 'landline_no', 'username',
'mobile_no_1', 'bank_name_1', 'bank_account_no_1', 'national_id', 'zip_code',
]
def __str__(self):
return self.email
class Meta:
verbose_name = 'contractor'
verbose_name_plural = 'contractors'
class Supervisor(User):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, parent_link=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)', null=True)
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', null=True)
landline_no = models.IntegerField(verbose_name='Work number')
mobile_no_1 = models.IntegerField(verbose_name='Mobile number')
mobile_no_2 = models.IntegerField(blank=True, verbose_name='Mobile number (#2)', null=True)
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)", null=True)
bank_account_no_2 = models.CharField(max_length=150, blank=True, verbose_name = 'Bank account number (#2)', null=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', 'postal_code', 'landline_no', 'username',
'mobile_no_1', 'bank_name_1', 'bank_account_no_1', 'national_id', 'zip_code',
]
def __str__(self):
return self.email
class Meta:
verbose_name = 'supervisor'
verbose_name_plural = 'supervisors'
views.py:
# Create your views here.
from django.shortcuts import render
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
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.set_password('raw_password')
user.save()
login(self.request, user)
return redirect('accounts/profile')
class ContractorSignUpView(CreateView):
model = Contractor
form_class = ContractorSignUp
template_name = 'registration/signup_form.html'
def get_context_data(self, **kwargs):
kwargs['user_type'] = 'contractor'
return super().get_context_data(**kwargs)
def form_valid(self, form):
user = form.save()
user.save()
user.set_password('raw_password')
login(self.request, user)
return redirect('accounts/profile')
class SupervisorSignUpView(CreateView):
model = Supervisor
form_class = SupervisorSignUp
template_name = 'registration/signup_form.html'
def get_context_data(self, **kwargs):
kwargs['user_type'] = 'supervisor'
return super().get_context_data(**kwargs)
def form_valid(self, form):
if form.is_valid():
user = form.save()
user.set_password('raw_password')
user.save()
login(self.request, user)
return redirect('accounts/profile')
EmailBackend.py:
from django.contrib.auth.backends import ModelBackend
from users.models import User
class Email_backend(object):
def authenticate(self, username=None, password=None):
try:
user=User.objects.get(email=username)
except User.DoesNotExist:
return None
if check_password(password, user.password):
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
login.html:
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}