https://docs.djangoproject.com/zh-hans/4.0/topics/auth/customizing/
SOP:
实际代码:
1.models.py覆盖User
class User(AbstractUser):
age = models.IntegerField(verbose_name=('年龄'),blank=True, null=True,)
mobilenumber = models.CharField(max_length=500,verbose_name=('电话号码'),blank=True, null=True,)
# userlink = models.OneToOneField(AbstractUser, on_delete=models.CASCADE, default=None, null=True)
2.admin.py
from django.contrib.auth.admin import UserAdmin
from .models import User
class UserAdmin(admin.ModelAdmin):
list_display = ('username',)
ordering = ('username',)
admin.site.register(User, UserAdmin)
3.settings.py
AUTH_USER_MODEL = 'book.User'
4.python manage.py makemigrations, python manage.py migrate
Migrations for 'book':
book\migrations\0027_auto_20230403_1636.py
- Alter field age on user
- Alter field mobilenumber on user
5.admin界面
6.在模板上可以使用
{% block permission_block %}
{% if request.user.is_authenticated %}
<div class="m-3">
用户:<span class="text-primary">{{ request.user.username }}</span>
姓名:<span class="text-primary">{{ request.user.age }}</span>
角色:<span class="text-primary">{{ request.user.mobilenumber }}</span>
</div>
{% endif %}
{% endblock %}
前端显示自定义User模型
forms.py
class theUserForm(ModelForm):
class Meta:
model = User
#fields = '__all__'
fields = ['username','password','dept','age','mobilenumber','role','theUser_status1',]
exclude = []
widgets = {
"password":wid.PasswordInput(render_value = True) # render_value = True显示值
}
# labels= {
# "theUser_logo":"用户头像",
# "theUser_status1":"生效状态",
# "theUser_status2":"借订书籍",
# }
# 循环找到所有的插件,加入css样式,添加 "class": "form-control"
bootstrap_exclude_fields = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环ModelForm中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
if name in self.bootstrap_exclude_fields:
continue
# class属性追加form-control,其他属性保留
if field.widget.attrs:
field.widget.attrs["class"] = field.widget.attrs.get('class','') + ' ' + 'form-control'
else:
field.widget.attrs = {
"class": "form-control",
}
View.py增删改查
def theUserlist_show(request,page=1):
theUserlist = User.objects.all()
# 添加分页功能
paginator = Paginator(theUserlist, 5)
try:
page_obj = paginator.page(page)
except PageNotAnInteger:
# 如果参数page 的数据类型不是整型,就返回第一页数据
page_obj = paginator.page(1)
except EmptyPage:
# 若用户访问的页数大于实际页数,则返回最后一页的数据
page_obj = paginator.page(paginator.num_pages)
return render(request,'theUserlist_show.html',locals())
def theUserlist_new(request):
if request.method == "GET":
form = theUserForm()
return render(request,'theUserlist_new.html',{'form':form})
# 用户POST请求提交数据,需要进行数据校验
form = theUserForm(data=request.POST,files=request.FILES)
if form.is_valid():
# print(form.cleaned_data)
# 直接保存至数据库
form.save()
return redirect("/theUserlist_show/")
return render(request,'theUserlist_new.html',{'form':form})
def theUserlist_edit(request,id):
row_obj = User.objects.filter(id=id).first()
if request.method == "GET":
form = theUserForm(instance=row_obj)
# 判断是否存在借订记录
theUser_fk_theBorrow_fk_theBook = []
for fk in row_obj.theborrow_set.all():
booklist = fk.theBorrow_theBook.theBook_name if fk else 'no-data'
theUser_fk_theBorrow_fk_theBook.append(booklist)
print(theUser_fk_theBorrow_fk_theBook)
return render(request,'theUserlist_edit.html',{'form':form,'theUser_fk_theBorrow_fk_theBook':theUser_fk_theBorrow_fk_theBook,})
# 用户POST请求提交数据,需要进行数据校验
form = theUserForm(data=request.POST,files=request.FILES, instance=row_obj)
if form.is_valid():
# print(form.cleaned_data)
# 直接保存至数据库
form.save()
return redirect("/theUserlist_show/")
return render(request,'theUserlist_edit.html',{'form':form})
def theUserlist_delete(request,id):
User.objects.get(id=id).delete()
return redirect("/theUserlist_show/")
外键修改
参考文章https://blog.csdn.net/zeaning/article/details/124110291
2个修复方法,只介绍方法1:
方法1:修改django_admin_log,把user_id关联的外键,改成自己定义的扩展User表
方法2:如果不想改,可以在测试环境(或新建个空的数据库),重新执行迁移,然后把新的django_admin_log表,通过数据库复制的方式,覆盖掉现有的django_admin_log表。
1.方法1–找到django_admin_log
2.方法1–修改user_id的外键
3.提交结构更改
4.拓展的user模型就可以改了。
自定义User无法登录,因为密码需要加密
1.没有加密的密码是无法登录的。
2.需要想办法加密。
方法1:处理密码放在form.save()之后,才能user登录。
from django.contrib.auth.hashers import make_password, check_password
def theUserlist_edit(request,id):
row_obj = User.objects.filter(id=id).first()
if request.method == "GET":
form = theUserForm(instance=row_obj)
# 判断是否存在借订记录
theUser_fk_theBorrow_fk_theBook = []
for fk in row_obj.theborrow_set.all():
booklist = fk.theBorrow_theBook.theBook_name if fk else 'no-data'
theUser_fk_theBorrow_fk_theBook.append(booklist)
print(theUser_fk_theBorrow_fk_theBook)
return render(request,'theUserlist_edit.html',{'form':form,'theUser_fk_theBorrow_fk_theBook':theUser_fk_theBorrow_fk_theBook,})
# 用户POST请求提交数据,需要进行数据校验
form = theUserForm(data=request.POST,files=request.FILES, instance=row_obj)
if form.is_valid():
# print(form.cleaned_data)
# 直接保存至数据库
form.save()
# 处理密码,才能user登录。
username = form.cleaned_data['username']
some_user = User.objects.filter(username = username).first()
some_user.password = make_password(form.cleaned_data['password'])
some_user.save()
return redirect("/theUserlist_show/")
return render(request,'theUserlist_edit.html',{'form':form})
方法2:利用form.py的super().clean()来处理密码加密
form.py
class theUserForm(ModelForm):
class Meta:
model = User
#fields = '__all__'
fields = ['username','password','dept','age','mobilenumber','role','theUser_status1',]
exclude = []
widgets = {
"password":wid.PasswordInput(render_value = True) # render_value = True显示值
}
labels= {
"username":"用户名",
"password":"密码",
}
# 循环找到所有的插件,加入css样式,添加 "class": "form-control"
bootstrap_exclude_fields = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环ModelForm中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
if name in self.bootstrap_exclude_fields:
continue
# class属性追加form-control,其他属性保留
if field.widget.attrs:
field.widget.attrs["class"] = field.widget.attrs.get('class','') + ' ' + 'form-control'
else:
field.widget.attrs = {
"class": "form-control",
}
# 全局钩子:验证数据并加密数据
def clean(self):
# 不能丢
super().clean()
pwd=self.cleaned_data.get("password")
if pwd:
self.cleaned_data['password'] = make_password(self.cleaned_data['password'])
else:
return self.cleaned_data