参考如下:
1. django 自定义用户user模型的三种方法
1.1 创建基于User
的proxy model,就是使用代理模型
1.2 使用abstractuser扩充fields
试验过,但是总是有报错,应该是哪里设置的问题。
复制代码 代码如下:
profiles/models.py from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _ # Create your models here.
class KarmaUser(AbstractUser):
karma = models.PositiveIntegerField(_("karma"),default=0,blank=True)
settings.py AUTH_USER_MODEL = 'profiles.KarmaUser'
1.3.使用一对一关系将相关的模型一个个联系起来,扩充原来的User模型
这很像django 1.5之前的方式.很适用于创建第三方扩充包的场景,松耦合,不会破坏之前项目的结构.
需要此方法的场景:
- 在自己的django prj下,希望有多重user拥有各自很不相同的字段.或许希望有些用户组合起来一些用户的类型字段,并且希望能在模型层面上解决这些问题.
例子如下:
profiles/models.py
复制代码 代码如下:
from django.conf import settings
from django.db import models from flavors.models import Flavor class EaterProfile(models.Model):
# 默认用户资料
user = models.OneToOneField(settings.AUTH_USER_MODEL)
favorite_ice_cream = models.ForeignKey(Flavor,null=True,blank=True) class ScooperProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
scoops_scooped = models.IntegerField(default=0) class InventorProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
flavors_invented = models.ManyToManyField(Flavor,null=True,blank=True)
1.4.继承abstractbaseuser来替代原来的User模型
只有当你对usermodel里面的默认字段不满的时候才要使用,这个方法只保留了passwork,last_login,is_active三个字段。
参考官方文档:
https://docs.djangoproject.com/en/1.7/topics/auth/customizing/
个人认为在我的建站场景中,第二种最合适.正在测试是否可以用抽象类简化模型.待续...
以上3种方法各有优劣,大家根据自己的需求,*选择吧。
2. OneToOneFiled的具体实现记录
1. 需求: 为了防止暴力破解,要求玩家连续登录5次错误之后帐号锁定10分钟(10分钟后自动解除锁定)。管理员可以手动解除锁定。用户登录成功后错误次数清零。
2. 做好的登录app目录如下:
3. 设计数据库 loginapp/models.py如下:
#-*- encoding:utf-8 -*- from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import User
from django.db import models
import datetime
import django.utils.timezone as timezone class Userotherstatus(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
is_freezed=models.BooleanField(default=False,help_text=u"帐号是否被冻结")
freezed_time=models.DateTimeField(null=True,blank=True,help_text=u"帐号冻结的时间点")
pass_errnum=models.IntegerField(default=0,help_text=u"密码已经错误次数")
注意:通过 python manage.py migrate将models应用导数据库后,创建用户过后,User模型一对一的Userotherstatus模型对应的数据库表里面没有数据。
解决办法使用 django signal。当我们创建和更新用户实例时,Userotherstatus模块也会被自动创建和更新。
4. signal 实现如下:
参考: https://blog.csdn.net/qq_32506555/article/details/53219036
参考: https://yiyibooks.cn/xx/Django_1.11.6/topics/signals.html
loginapp/signals.py
#-*- encoding: utf-8 -*- from django.db.models.signals import post_save
from django.contrib.auth.models import User
from .models import Userotherstatus
from django.dispatch import receiver @receiver(post_save, sender=User)
def creat_user_otherstatus(sender,instance,created,**kwargs):
print "use signal creat"
if created:
Userotherstatus.objects.create(user=instance) @receiver(post_save, sender=User)
def save_user_otherstatus(sender, instance, **kwargs):
print (" use signal save")
instance.userotherstatus.save() #
signal 信号注册:
loginapp/apps.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from django.apps import AppConfig class LoginappConfig(AppConfig):
name = 'loginapp' def ready(self):
import loginapp.signals
loginapp/__init__.py
default_app_config = 'loginapp.apps.LoginappConfig'
5. 后台views的实现 loginapp/views.py:
思路:
帐号是否锁定》锁定》判断是否过了锁定时间》是》解锁并且错误次数设置为0
否》提示处于锁定状态
》没锁定 》判断错误次数
》都不满足进行登录验证
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.models import User
# from django.contrib.auth.models import BaseUserManager
# from django.contrib.auth.hashers import make_password, check_password
# from django.views.generic.base import View
import datetime
from LoginForm import MyLoginForm
from loginapp.models import Userotherstatus
from django.views.decorators.csrf import csrf_protect,requires_csrf_token
# Create your views here. @requires_csrf_token
@csrf_protect
def MyLogin(request):
lock_time=60
pass_error_limit=5
form = MyLoginForm() if request.method=="POST":
print request.path
#验证表单
form = MyLoginForm(request.POST)
if form.is_valid():
username=request.POST["username"]
password=request.POST["password"] #验证用户
try:
user_id=User.objects.get(username=username).id
print 1111111111111111111111
except Exception:
return render(request,'loginapp/login.html',{'form':form,'msg':"用户不存在"})
freezed_time=Userotherstatus.objects.get(user_id=user_id).freezed_time
pass_errornum=Userotherstatus.objects.get(user_id=user_id).pass_errnum
is_freezed=Userotherstatus.objects.get(user_id=user_id).is_freezed print(freezed_time,pass_errornum,is_freezed) if is_freezed==True and freezed_time:
print 2222222222222222222222
print ((datetime.datetime.now() - (freezed_time.replace(tzinfo=None))).total_seconds()) if (datetime.datetime.now()-(freezed_time.replace(tzinfo=None))).total_seconds()>lock_time:
print("重置")
Userotherstatus.objects.filter(user_id=user_id).update(is_freezed=False,pass_errnum=0)
# Userotherstatus.objects.filter(user_id=user_id).update()
user=authenticate(username=username,password=password)
if user is not None and user.is_active:
login(request,user)
User.last_login=datetime.datetime.now() return HttpResponse("登录成功") else :
return render(request,'loginapp/login.html',
{'form':form,'msg':'帐号锁定中,请稍后再尝试,需要解锁请联系管理员!'}) if pass_errornum>=5:
print 33333333333333333 Userotherstatus.objects.filter(user_id=user_id).update(is_freezed=True,pass_errnum=0)
Userotherstatus.objects.filter(user_id=user_id).update(freezed_time=datetime.datetime.now()) return render(request,'loginapp/login.html',
{'form':form,'msg':"密码连续错误5次,帐号已经被锁定"}) else:
user=authenticate(username=username,password=password)
if user is not None and user.is_active:
login(request, user)
User.last_login = datetime.datetime.now()
Userotherstatus.objects.filter(user_id=user_id).update(is_freezed=False,pass_errnum=0)
# Userotherstatus.objects.filter(user_id=user_id).update()
return HttpResponse("登录成功")
else:
print 4444444444444444444444
Userotherstatus.objects.filter(user_id=user_id).update(pass_errnum=(int(pass_errornum)+1)) return render(request, 'loginapp/login.html',
{'form': form}) else:
return render(request,'loginapp/login.html',
{'form':form})
6. 附上 表单 loginapp/LoginForm.py
#-*- encoding: utf-8 -*- from django import forms class MyLoginForm(forms.Form): username=forms.CharField(label="inputUser",
max_length=20,
error_messages={'required':"请输入用户名"},
widget=forms.TextInput(
attrs={
'placeholder':"User Name",
'required':'True',
'class':'form-control'
})
)
password=forms.CharField(label="inputPassword",
max_length=100,
error_messages={'required':"请输入密码"},
widget=forms.PasswordInput(
attrs={
'placeholder': "Password",
'required':"True",
'class':'form-control',
})
)
7. 附上 login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../static/favicon.ico"> <title>Signin Page</title> <!-- Bootstrap core CSS -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<link href="../static/css/ie10-viewport-bug-workaround.css" rel="stylesheet"> <!-- Custom styles for this template -->
<link href="../static/css/signin.css" rel="stylesheet"> <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../static/js/ie8-responsive-file-warning.js"></script><![endif]-->
<script src="../static/js/ie-emulation-modes-warning.js"></script> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head> <body> <div class="container"> <form class="form-signin" action="" method="post">
{% csrf_token %}
<h2 class="form-signin-heading">Please sign in</h2>
{{form.username.errors}}
{{form.username.lable_tag}}
{{form.username}} {{form.password.errors}}
{{form.password.lable_tag}}
{{form.password}}
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
{{msg}}
</form> </div> <!-- /container --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../static/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html> <!--<form class="form-signin" action="" method="post">-->
<!--<h2 class="form-signin-heading">Please sign in</h2>-->
<!--<label for="inputUser" class="sr-only">User</label>-->
<!--<input type="text" id="inputUser" class="form-control" placeholder="User Name" required autofocus>-->
<!--<label for="inputPassword" class="sr-only">Password</label>-->
<!--<input type="password" id="inputPassword" class="form-control" placeholder="Password" required>-->
<!--<div class="checkbox">-->
<!--<label>-->
<!--<input type="checkbox" value="remember-me"> Remember me-->
<!--</label>-->
<!--</div>-->
<!--<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>-->
<!--</form>-->
User模型扩展和自定义的更多相关文章
-
python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API
python Django教程 之 模型(数据库).自定义Field.数据表更改.QuerySet API 一.Django 模型(数据库) Django 模型是与数据库相关的,与数据库相关的代码 ...
-
Entity Framework 6 Recipes 2nd Edition(10-5)译 ->; 在存储模型中使用自定义函数
10-5. 在存储模型中使用自定义函数 问题 想在模型中使用自定义函数,而不是存储过程. 解决方案 假设我们数据库里有成员(members)和他们已经发送的信息(messages) 关系数据表,如Fi ...
-
扩展 ASP.NET MVC 模型扩展 &ndash; ASP.NET MVC 4 系列
大部分人不能将核心运行时(System.Web 中的类)和 ASP.NET Web Forms 应用程序平台(System.Web.UI 中的类)区分开来. ASP.NET ...
-
C#Winform使用扩展方法自定义富文本框(RichTextBox)字体颜色
在利用C#开发Winform应用程序的时候,我们有可能使用RichTextBox来实现实时显示应用程序日志的功能,日志又分为:一般消息,警告提示 和错误等类别.为了更好地区分不同类型的日志,我们需要使 ...
-
Qt之模型/视图(自定义进度条)
简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstr ...
-
Qt之模型/视图(自定义风格)
Qt之模型/视图(自定义风格) 关于自定义风格是针对视图与委托而言的,使用事件与QSS都可以进行处理,今天关于美化的细节讲解一下. 先看下图: 先撇开界面的美观性(萝卜青菜,各有所爱),就现有的这些风 ...
-
【数据库上】第五讲 E-R模型扩展知识
第五讲 E-R模型扩展知识 一.E-R模型设计主意问题 1.1 用实体还是实体集 案例:学院对象的表示 应将各个学院看做实体集,还是实体? 方法一:将各个学院看作一个实体集 如果各学院具有不同属性特征 ...
-
EMF学习,为了实现可扩展可自定义的模型验证 - 各种实现方法学习
自: http://blog.csdn.net/javaman_chen/article/details/6057033 http://www.ibm.com/developerworks/cn/op ...
-
EMF学习,为了实现可扩展可自定义的模型验证 - emf quary 与 OCL
http://blog.csdn.net/javaman_chen/article/details/6020050 //这里的验证强调的是condition的构造,基于查找来判断验证结果.支持OCL也 ...
随机推荐
-
XML带多属性解析为一个实体类(利用反射)
最近在对接一个银行的项目,大概就是类似一个钱包的功能,在请求返回的数据时,发现返回的数据标准的XML格式的支付串,格式如下 <kColl id="inputOrig" app ...
-
浅谈WEB跨域的实现(前端向)
同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS.CSFR等攻击(可以参考我的这篇文章). SOP要求 ...
-
查看package编译时的错误信息及重新编译
开发时,一般都是使用PL/SQL工具进行开发,查看编译错误及重新编译都很简单,但是一般的生产环境是不允许连接外界工具的,只能在命令行中进行重新编译及查看,今天我就遇到了这个问题,现在总结如下: 1.获 ...
-
mysql:恢复mysql表结构
mysql,frm格式恢复mysql表结构,以tuser.frm格式为例 新增数据库,如下,创建数据库名为ab 打开数据库,双击打开数据库 点右键新建表结构 新增表,里面只添加一个字段 ...
-
React Native(ios)项目中logo,启动屏设置
由于logo和启动屏尺寸多,react native(ios)中没有命令可以自动生成各种的尺寸,所以可以使用以下办法:在ionic项目中生成(使用命令:ionic resources)后,再粘贴到re ...
-
第二十八篇、自定义的UITableViewCell上有图片需要显示,要求网络网络状态为WiFi时,显示图片高清图;网络状态为蜂窝移动网络时,显示图片缩略图
1)SDWebImage会自动帮助开发者缓存图片(包括内存缓存,沙盒缓存),所以我们需要设置用户在WiFi环境下下载的高清图,下次在蜂窝网络状态下打开应用也应显示高清图,而不是去下载缩略图. 2)许多 ...
-
NonUniqueObjectException 问题
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was alread ...
-
ffmpeg的安装--opencv视频处理必备
安装yasm(ffmpeg必备)wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gztar xzvf yasm-1. ...
-
《JS权威指南学习总结--1.1语言核心》
1.1语言核心 --本节主要介绍<js权威指南>基础部分各章讲解内容和一些简单的示例 本小节内容: 一.第二章讲解js注释.分号和Unicode,第三章主要讲解js变量和赋值 简单示例: ...
-
localStorage与sessionStorage区别
localStorage与sessionStorage区别:浏览器正常模式下: 关闭浏览器或该窗口标签时,localStorage数据依然保存,但是sessionStorage数据会被清除. ...