热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

User模型扩展和自定义

参考如下:django文档参考djangosignal使用总结django信号注册django信号问题1djangooneTooneFiled

参考如下:

django文档参考

django signal使用总结

django 信号注册

django信号问题1

django oneTooneFiled

 

 
 

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 

"zh-CN">
  
    "utf-8">
    "X-UA-Compatible" cOntent="IE=edge">
    "viewport" cOntent=">
    
    "description" cOntent="">
    "author" cOntent="">
    "icon" href="../static/favicon.ico">

    

    
    "https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    
    "../static/css/ie10-viewport-bug-workaround.css" rel="stylesheet">

    
    "../static/css/signin.css" rel="stylesheet">

    
    
    

    
    
  

  

    
class="container"> class="form-signin" action="" method="post"> {% csrf_token %}

class="form-signin-heading">Please sign in

{{form.username.errors}} {{form.username.lable_tag}} {{form.username}} {{form.password.errors}} {{form.password.lable_tag}} {{form.password}}
class="checkbox">
{{msg}}

 


推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
author-avatar
亮仔
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有