所以我使用自定义用户模型
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self, email, full_name, address, number, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
if not full_name:
raise ValueError('Users must have an email address')
if not address:
raise ValueError('Users must have an email address')
if not number:
raise ValueError('Users must have an email address')
if not password:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email.lower()),
full_name=full_name,
address = address,
number=number,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, full_name, address, number, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
email,
full_name,
address,
numbe,
password = password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, full_name, address, number, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
email,
full_name,
address,
number,
password = password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
full_name = models.CharField(max_length=255, blank = False, null = False)
address = models.CharField(max_length=255, blank = False, null = False)
number = models.CharField(max_length=255, blank = False, null = False)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name', 'address', 'number'] # Email & Password are required by default.
objects = UserManager()
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
@property
def is_staff(self):
"Is the user a member of staff?"
return self.staff
@property
def is_admin(self):
"Is the user a admin member?"
return self.admin
@property
def is_active(self):
"Is the user active?"
return self.active
这是我的应用程序的admin.py
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminChangeForm, UserAdminCreationForm
from .models import User
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'admin')
list_filter = ('admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('full_name', 'address', 'number')}),
('Permissions', {'fields': ('admin', 'active', 'staff')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'full_name', 'address', 'number', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
admin.site.unregister(Group)
最后是forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User
class UserAdminCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email', 'full_name', 'address', 'number')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'full_name', 'address', 'number', 'password', 'active', 'admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
因此,当我使用manage.py通过控制台创建超级用户时效果很好但是当我决定在gui管理面板中编辑,删除或创建另一个用户时,我得到一个" FOREIGN KEY约束失败" 。我不明白,有人能指出我正确的方向吗?
答案 0 :(得分:2)
我想我找到了解决方案。当您将默认AUTH_USER_MODEL迁移到项目中间的自定义模型时,问题很可能是由循环依赖性问题引起的。
来自Django文档
在创建数据库表之后更改AUTH_USER_MODEL要困难得多,因为它会影响外键和多对多关系,例如。
此更改无法自动完成,需要手动修复架构,从旧用户表移动数据,并可能手动重新应用某些迁移。有关步骤的概述,请参阅#25313。
由于Django对可交换模型的动态依赖特性的限制,AUTH_USER_MODEL引用的模型必须在其app的第一次迁移中创建(通常称为0001_initial);否则,你会有依赖性问题。
此外,在运行迁移时可能会遇到CircularDependencyError,因为Django由于动态依赖性而无法自动中断依赖循环。如果您看到此错误,则应通过将用户模型所依赖的模型移动到第二次迁移中来中断循环。 (你可以尝试制作两个相互具有ForeignKey的普通模型,看看makemigrations如何解决循环依赖关系,如果你想看看它是如何完成的。)
解决此问题的最佳方法是删除表并删除所有迁移文件,然后使用新制作的自定义模型重新运行迁移。希望这会奏效。
有关如何从内置模型迁移到新模型的更多详细信息,请访问https://code.djangoproject.com/ticket/25313
答案 1 :(得分:1)
我四处询问,代码应该适用于旧版本的django。可悲的是,它在django 2.0或以上版本中无法工作。如果有人想要替代方案,我发现this对我的项目来说是完美的,解释也很简单。
答案 2 :(得分:0)
对于Django 2.2 +:
答案 3 :(得分:0)
警告:它将删除整个数据库。如果您有一些重要数据,请通过dumpdata进行备份,然后通过loaddata进行恢复。 for more info check here (I am not sure about this).
在项目中间更改AUTH_USER_MODEL非常困难。 See the note in the docs。
第一次迁移Django表完成后感染,您将面临问题。
想法是:您需要在首次迁移(其中django)中将自定义用户模型及其条目包含在setting.py(AUTH_USER_MODEL = [自定义用户模型])中创建自己的表,例如Django项目的auth_group,dajango_migrations等...)。
警告:如果您已启动服务器,则Django会自己创建数据库,然后这将无法正常工作,因此请不要启动服务器。
完成了。
现在您可以启动服务器了。
然后取消注释所有其他模型并迁移它们。