目录:Django其他篇
05:ModelForm 数据验证 & 生成html & 数据库操作
目录:
- 1.1 Django Admin基本使用
- 1.2 admin.py中用来自定制常用参数
- 1.3 定制:增加、修改、删除前执行函数
- 1.4 Django admin的一些有用定制
- 1.5 重写Django Admin用户认证
1.1 Django Admin基本使用 返回顶部
1、Django Admin 基本使用演示
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.db import models class User(models.Model): username = models.CharField(max_length=32,verbose_name='用户名') pwd = models.CharField(max_length=64,verbose_name='密码') ctime = models.DateTimeField(auto_now=True) ut = models.ForeignKey(to='UserType',to_field='id',verbose_name='用户类型') m2m = models.ManyToManyField("Group") def __str__(self): return self.username class Meta: verbose_name_plural = '用户表' class UserType(models.Model): user_type_name = models.CharField(max_length=32) def __str__(self): return self.user_type_name class Group(models.Model): group_name = models.CharField(max_length=32) def __str__(self): return self.group_name
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.contrib import admin from app01 import models class UserAdmin(admin.ModelAdmin): list_display = ('username','pwd','ut','ctime',) admin.site.register(models.User,UserAdmin) admin.site.register(models.UserType) admin.site.register(models.Group)
2、简单说明
1. 在admin.py中可以使用 list_display 指定显示那些字段,但是不能显示多对多字段
2. 在创建时一对多显示为单选下拉菜单,多对多显示为多选下拉菜单
1.2 admin.py中用来自定制常用参数 返回顶部
1、UserAdmin自定制常用参数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.contrib import admin from app01 import models class UserAdmin(admin.ModelAdmin): list_display = ('username','pwd','ut','ctime',) list_filter = ('source','consultant','date') #过滤字段 search_fields = ('qq','name') #搜索匹配字段 raw_id_fields = ('consult_course',) filter_horizontal = ('tags',) #多对多字段显示 list_per_page = 1 #每页显示几条数据 list_editable = ('source',) #可编辑的字段 readonly_fields = ('qq',) #只读字段 exclude = ('name',) # 添加和修改时那些界面不显示 date_hierarchy = 'ctime' # 详细时间分层筛选 actions = ['test_action',] #之定义的action函数 def test_action(self, request, arg2): # 自定义action函数 ''' :param self: crm.CustomerAdmin类本身 :param request: 客户端request请求 :param arg2: 前端选中的数据实例 ''' admin.site.register(models.User,UserAdmin) admin.site.site_header = '重写DjangoAdmin管理系统' # 修改系统显示名称 admin.site.site_title = '我的后台管理界面' # 修改页面 title
2、将页面显示成中文(在settings.py中修改)
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
3、修改页面项目显示名称 (admin.py中修改)
admin.site.site_header = '重写DjangoAdmin管理系统' # 修改系统显示名称
admin.site.site_title = '我的后台管理界面' # 修改页面 title
1.3 定制:增加、修改、删除前执行函数 返回顶部
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
# admin.py from django.contrib import admin from app01 import models class UserAdmin(admin.ModelAdmin): list_display = ('username','pwd','ut','ctime',) # 通过change参数,可以判断是修改还是新增,同时做相应的操作 def save_model(self, request, obj, form, change): if change: # 更改的时候 print('修改会执行这里') else: # 新增的时候 print('新增会执行这里') super(UserAdmin, self).save_model(request, obj, form, change) def delete_model(self, request, obj): print('删除时会执行这里') obj.delete() admin.site.register(models.User,UserAdmin)
1.4 Django admin的一些有用定制 返回顶部
1、字段级别的权限
作用:不同权限的可以编辑不同的内容,可以通过get_readonly_fileds()来添加字段只读权限。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class EntryAdmin(admin.ModelAdmin): list_display=(...) search_fields=(...) def get_readonly_fields(self,request,obj=None): if not request.user.is_superuser and not request.user.can_edit: return [f.name for f in self.model._meta.fields] return self.readonly_fields
2、不同的用户显示不同的数据行,重写列表页面返回的查询集
作用:ModelAdmin提供了一个钩子程序 —— 它有一个名为queryset()
的方法,该方法可以确定任何列表页面返回的默认查询集。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class MyModelAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super(MyModelAdmin, self).get_queryset(request) if request.user.is_superuser: return qs return qs.filter(author=request.user)
1.5 重写Django Admin用户认证 返回顶部
1、说明
1. Django Admin中通过python manage.py createsuperuser创建的用户默认存储在自己的User表中
2. 很多时候我们想要借助这个用户认证,但是Django中自带的User表我们是无法添加其他字段的
3. 所以为了更方便的使用Django admin的认证功能,可以使用我们自己的UserProfile表代替Django Admin的User表
2、重写步骤
1、models.py中定义表结构
2、admin.py中注册UserProfile表,并定制UserProfileAdmin
注:如果只定义表结构而没有定制UserProfileAdmin,在页面创建的用户密码为明文,无法登陆admin后台
3、一定要记得到settings.py指定使用我们自定义的UserProfile表做登录验证
4、执行创建表命令
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
5、此时就可以登陆admin后台创建用户,修改面等操作了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.db import models from django.utils.translation import ugettext_lazy as _ #国际化 from django.utils.safestring import mark_safe from django.contrib.auth.models import ( BaseUserManager, AbstractBaseUser,PermissionsMixin ) #1. 创建用户时调用这个类 class UserProfileManager(BaseUserManager): #这个方法用来创建普通用户 def create_user(self, email, name, password=None): if not email: raise ValueError('Users must have an email address') user = self.model( #验证email email=self.normalize_email(email), name=name, ) user.set_password(password) #让密码更安全,设置密码,给密码加盐 self.is_active = True #指定创建用户默认是active user.save(using=self._db) #保存创建信息 return user def create_superuser(self, email, name, password): #这个方法用来创建超级用户 user = self.create_user( email, password=password, name=name, ) user.is_active = True user.is_admin = True user.save(using=self._db) return user #2 创建UserProfile表替代Django admin中的user表做用户登录 class UserProfile(AbstractBaseUser,PermissionsMixin): email = models.EmailField( verbose_name='email address', max_length=255, unique=True, null=True ) password = models.CharField(_('password'), max_length=128,help_text=mark_safe('''<a href='password/'>修改密码</a>''')) name = models.CharField(max_length=32) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) #roles = models.ManyToManyField("Role",blank=True) objects = UserProfileManager() #创建用户时会调用这里类 USERNAME_FIELD = 'email' #自己指定那个字段作为用户名 REQUIRED_FIELDS = ['name'] #那些字段是必须的 # 下面这些是默认方法不必修改它 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): #对用户授权(如果注释掉用户登录后没任何表权限) return True def has_module_perms(self, app_label): #对用户授权(如果注释掉用户登录后没任何表权限) return True @property def is_staff(self): #return self.is_admin #这个必须是指定admin才能登陆Django admin后台 return self.is_active #这个只要用户时is_active的即可登陆Django admin后台
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#解决我们改写的Django admin 中user表验证时密码明文问题 from django.contrib import admin from django import forms from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField from app01 import models #1、不必改什么(创建用户时调用这个类) class UserCreationForm(forms.ModelForm): password1 = forms.CharField(label='Password', widget=forms.PasswordInput) password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) class Meta: model = models.UserProfile fields = ('email', 'name') def clean_password2(self): 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(UserCreationForm, self).save(commit=False) user.set_password(self.cleaned_data["password1"]) if commit: user.save() return user #2、不必改什么(修改用户时调用这个类) class UserChangeForm(forms.ModelForm): password = ReadOnlyPasswordHashField() class Meta: model = models.UserProfile fields = ('email', 'password', 'name', 'is_active', 'is_admin') def clean_password(self): return self.initial["password"] #3、定制UserProfile表 class UserProfileAdmin(BaseUserAdmin): # The forms to add and change user instances form = UserChangeForm add_form = UserCreationForm list_display = ('email', 'name', 'is_admin',"is_staff",'password') list_filter = ('is_admin',) fieldsets = ( (None, {'fields': ('email', 'password')}), ('Personal', {'fields': ('name',)}), ('Permissions', {'fields': ('is_admin',"is_active","user_permissions",'groups')}), # ('Permissions', {'fields': ('is_admin',"roles","is_active","user_permissions",'groups')}), ) #Permissions后的字典记得加上,is_admin,is_active否则我们无法再前端勾选,那么我们自己新建的用户无法登陆Django Admin后台 add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'name', 'password1', 'password2')} # 'fields': ("roles",'email', 'name', 'password1', 'password2')} ), ) search_fields = ('email',) ordering = ('email',) filter_horizontal = ("user_permissions",'groups',) #显示多对多的选项框 admin.site.register(models.UserProfile, UserProfileAdmin) admin.site.unregister(Group)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
AUTH_USER_MODEL = 'app01.UserProfile' #app名.表名
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.shortcuts import render,HttpResponse,redirect from django.contrib.auth import login,authenticate,logout from django.contrib.auth.decorators import login_required #装饰器,用来验证用户是否登录 def acc_login(request): errors = {} if request.method == 'POST': _email = request.POST.get('email') _password = request.POST.get('password') user = authenticate(username= _email, password=_password) #通过验证会返回一个user对象 print('user',user) if user: login(request,user) #Django自动登录,然后创建session next_url = request.GET.get("next","/crm/") #未登录时直接输入url时跳转到登录界面是会加上"next"参数 return redirect(next_url) else: errors['error'] = "Wrong username or password!" return render(request,'login.html',{'errors':errors}) def acc_logout(request): logout(request) return redirect("/account/login/")