form表单使用(博客系统的登陆验证,注册)
先从小的实例来看form的用法
登陆验证实例,来看form的常规用法
1. forms.py
# 用于登陆验证验证
from django.core.validators import RegexValidator 支持正则
# 登陆验证手动触发错误对象
from django.core.exceptions import ValidationError # 登陆规则
class loginform(Form):
name = fields.CharField(
required=True,
min_length=3,
max_length=18,
error_messages={
'required':'用户不能为空',
'min_length':'用户长度不能小于3',
'max_length':'用户长度不能大于18',
}
)
pwd = fields.CharField(
required=True,
min_length=3,
max_length=18,
error_messages={
'required': '用户不能为空',
'min_length': '用户长度不能小于3',
'max_length': '用户长度不能大于18',
'invalid':'密码格式错误', #自定义错误,优先级高
},validators=[RegexValidator('\d+','只能是数字',code)] #只能是数字也是报错信息,不过优先级低,也就是说如果用户输入非数字,那么提示invalid错误,如果invalid没有,那么报‘只能是数字’错误,code就是给invalid重新命名而已,没有什么用处,可以不写) # from扩展,可以直接在里面进行数据库操作,场景注册,局部钩子,博客系统注册,详细介绍了用法,见下文#######
def clean_name(self):
# 验证可以直接写在这里,进行验证,返回可以是任意类型,重新赋值给clean_date里面的user
user = self.cleaned_data['name']
is_exsit = models.UserInfo.objects.filter(name=user).count()
if not is_exsit:
raise ValidationError('用户名不存在')
return user def clean_pwd(self):
# 这里可以匹配数据库其他校验,返回可以是任意类型,重新赋值给clean_date里面的pwd
return True
2. views.py
def login(request):
if request.method=='GET':
form = loginform()
return render(request,'login.html',{'form':form})
elif request.method=='POST':
form = loginform(request.POST) # 前端提交数据给form
# 规则验证
if form.is_valid():
# 数据库验证
print('name',form.cleaned_data['name'])
user_obj = models.UserInfo.objects.filter(**form.cleaned_data).first()
if not user_obj:
form.add_error('pwd',ValidationError('用户名或者密码错误')) #当你符合格式,但是数据库没有的时候就会报错,跟局部钩子触发错误是一样的
return render(request,'login.html',{'form':form})
else:
print(form.cleaned_data['name'])
work_boj = models.Workers.objects.filter(utow__name=form.cleaned_data['name'], utow__pwd=form.cleaned_data['pwd']).first()
work = work_boj.workname
request.session[settings.USEROBJ] = {'username': user_obj.name, 'work': work}
return redirect('/index/')
else:
return render(request,'login.html',{'form':form})
else:
return HttpResponse('访问请求非get,post')
3. login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<form method="POST">
{% csrf_token %}
<p>{{ form.username }} {{ form.errors.username.0 }} </p>
<p>{{ form.password }} {{ form.errors.password.0 }} </p>
<input type="submit" value="提交" />
</form>
</body>
</html>
通过问卷的创建修改来看form的高级用法forms.fields.ChoiceField
主要了解下 forms.fields.ChoiceField(choices=[(1,'a'),(2,'b')]),和初始化数据
models.py
class UserInfo(models.Model):
"""
员工表
"""
name = models.CharField(max_length=32) def __str__(self):
return self.name class ClassInfo(models.Model):
"""
班级表
"""
name = models.CharField(max_length=32)
def __str__(self):
return self.name class Questionnaire(models.Model): # 问卷: 班级 :创建者
"""
问卷表 """
title = models.CharField(max_length=64)
cls = models.ForeignKey(to=ClassInfo)
creator = models.ForeignKey(to=UserInfo) def __str__(self):
return self.title
1. forms.py
from django import forms
from django.forms import widgets # 插件,可以插入些样式
from django.core.exceptions import ValidationError # 手动触发错误
from django.core.validators import RegexValidator # 支持正则 from app01 import models from django.forms.models import ModelChoiceField # 下拉框实时刷新第二种方法 class questionnaire_form(forms.Form): # 问卷规则
title = forms.fields.CharField(required=True,
error_messages={'required':'名称不能为空','invalid':'格式错误'},
widget=widgets.TextInput(attrs={'placeholder':'问卷名称',
'class':'form-control questionnaire_title'},)) # 其他框使用
# password = forms.fields.CharField(required=True, error_messages={'required': '密码不能为空'},
#widget=widgets.TextInput(attrs={'placeholder': '密码', 'class': 'form-control'})) # 不能为空
# email = forms.fields.EmailField(required=True, error_messages={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'},
# widget=widgets.PasswordInput(attrs={'placeholder': '邮箱', 'class': 'form-control'})) # 不能为空,且邮箱格式
# text = forms.fields.CharField(required=True,error_messages={'required':'密码不能为空'},
# widget=widgets.Textarea(attrs={'class':'textatea'}))
# cls_list = fields.MultipleChoiceField(choices=[]) # 多选框,传过来的值,是列表
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# self.fields['cls_list'].choices = models.ClassList.objects.values_list('id', 'caption') # 第一种实时刷新,通过重构init方法,不需要models的str方法
# cls_id = forms.fields.ChoiceField(choices=[])
# creator_id = forms.fields.ChoiceField(choices=[])
# def __init__(self,*args,**kwargs):
# super().__init__(*args,**kwargs)
# 不需要重启,修改后提交后,再点进来可以保证修改完成
# self.fields['cls_id'].choices= models.ClassInfo.objects.all().values_list('id','name')
# self.fields['creator_id'].choices = models.UserInfo.objects.all().values_list('id','name') # 第二种实时刷新,需要models里面的str方法,不然下拉框都是对象,访问数据库因为返回的是对象
cls_id = ModelChoiceField(queryset=models.ClassInfo.objects.all())
creator_id = ModelChoiceField(queryset=models.UserInfo.objects.all()) # 局部钩子
def clean_title(self): # 针对添加的时候,如果有questionnaire_title,就存在,没有可以正常进行
questionnaire_title = models.Questionnaire.objects.filter(title=self.cleaned_data.get('title')) # 前端传来的数据保存在clean_data里
if not questionnaire_title:
return self.cleaned_data.get('title')
else:
raise ValidationError('用户名已经存在') # 触发错误
2. views.py
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from .forms import *
from app01 import models def questionnaire_list(request):
'''
问卷首页,格式:8000/questionnaire首页,
:param request:
:param questionnaire_id:
:return:
'''
questionnaire_list = models.Questionnaire.objects.all() # 所有问卷
return render(request, "questionnaire_list.html", {'questionnaire_list':questionnaire_list}) def add_questionnaire_obj(request,**kwargs):
'''
添加问卷
:param request:
:param kwargs:
:return:
'''
if request.method == 'GET':
form = questionnaire_form()
return render(request, 'add_questionnaire_obj.html',{'form':form})
elif request.method == 'POST':
form = questionnaire_form(request.POST)
print(request.POST)
# 校验
if form.is_valid():
print(form.cleaned_data)
# 下拉框第二种实时更新方法,因为前端是queryset对象,所以需要把cleand_data数据重新更改一下
# form.cleaned_data['creator_id'] = form.cleaned_data['creator_id'].id
# form.cleaned_data['cls_id'] = form.cleaned_data['cls_id'].id
models.Questionnaire.objects.create(**form.cleaned_data)
return redirect('/questionnaire/')
else:
return render(request, 'add_questionnaire_obj.html', {'form': form}) def edit_questionnaire_obj(request,**kwargs):
'''
问卷对象,格式:8000/questionnaire/questionnaire_id,选中问卷编辑
:param request:
:param kwargs:
:return:
'''
questionnaire_id = kwargs.get('questionnaire_id') # 得到需要编辑的问卷的ID
if request.method == 'GET':
questionnaire_obj = models.Questionnaire.objects.filter(id=questionnaire_id).first() # 通过ID找到问卷对象
# form的实例化,initial初始化,适用于初始默认的值,
# form = questionnaire_form(),没有数据,只是可以在前端渲染标签,需要在FORM里面执行,例如TEXTIINPUT
# form = questionnaire_form(data=request.POST),有数据,并且到FORM里面进行验证
# 初始化的值,initial={'对象字段名称':,'对象字段,如果是关联字段加上ID,也就是数据库字段是什么,就是什么':}
# 初始化的字段名称最好跟MODELS的一样,FORM验证最好也是一样,前端也是一样,这样确保可以正常 ########### 注意
form = questionnaire_form(initial={"title":questionnaire_obj.title, "cls_id":questionnaire_obj.cls_id,"creator_id":questionnaire_obj.creator_id}) # 默认值
return render(request, "edit_questionnaire_obj.html", {'form': form})
if request.method == 'POST':
form =questionnaire_form(data=request.POST)
if form.is_valid():
print(form.cleaned_data)
print(form.errors)
models.Questionnaire.objects.filter(id=questionnaire_id).update(**form.cleaned_data)
return redirect('/questionnaire/')
else:
return render(request, 'edit_questionnaire_obj.html', {'form': form})
3. questionnaire_obj.html
<form action="" method="post">
{% csrf_token %}
<p>问卷调查名称:{{ form.title }}</p>
<p>选择班级:{{ form.cls_id }}</p>
<p>选择创建者:{{ form.creator_id }}</p>
<input type="submit" value="提交">
</form>
博客系统注册,读完肯定清晰明了,注意这里面有全局钩子的用法,
针对from.error下的__all__
models结构如下
class UserInfo(AbstractUser):
"""
用户信息
"""
nid = models.AutoField(primary_key=True)
nickname = models.CharField(verbose_name='昵称', max_length=32)
telephone = models.CharField(max_length=11, null=True, unique=True)
avatar = models.FileField(upload_to='avatar/',default="/avatar/default.png")
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
blog = models.OneToOneField(to='Blog', to_field='nid',null=True) def __str__(self):
return self.username
forms
from django import forms
from django.forms import widgets from . models import UserInfo
from django.core.exceptions import NON_FIELD_ERRORS,ValidationError # 手动触发错误 class RegForm(forms.Form): # 子类
# widget 默认情况下,CharField 具有一个TextInput 在HTML 中生成一个<input type="text">
# attrs 可以对input标签添加属性
def __init__(self,request,*args,**kwargs): # 派生方法
super().__init__(*args,**kwargs)
self.request = request # 派生属性
user = forms.CharField(min_length=5,max_length=12,required=True, # 规则
error_messages={'min_length':'最小长度5','max_length':'最大长度12','required':'不能为空'}, # 错误信息
widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'username'})) # 生成标签,标签属性 pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'password'})) repeat_pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'repeat_password'})) email = forms.EmailField(required=True,error_messages={'invalid':'格式错误','required':'不能为空'},
# 生成一个EmailInput <input type="input">
widget = widgets.EmailInput(attrs={'class':'form-control','placeholder':'email','required':'不能为空'})) valid_code = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'valid_code'})) # 局部钩子,针对user的验证
def clean_user(self):
user = UserInfo.objects.filter(username=self.cleaned_data.get('user'))
if not user:
return self.cleaned_data.get('user')
else:
raise ValidationError('用户名已经存在') # 局部钩子,针对pwd的验证
def clean_pwd(self):
pwd = self.cleaned_data.get('pwd')
if pwd.isdigit() or pwd.isalpha():
raise ValidationError('不能是纯数字或者纯字母')
else:
return pwd # 局部钩子,针对验证码的验证
def clean_valid_code(self):
val = self.cleaned_data.get('valid_code')
if val.upper() == self.request.session.get('valid_code_str').upper():
return val
else:
raise ValidationError('验证码错误') # 全局钩子,针对全局上的验证,注意,先走局部后走全局
def clean(self):
if self.cleaned_data.get('pwd'):
if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
return self.cleaned_data
else:
raise ValidationError('俩次密码不一致') # 正确信息保存在,clean.data
# 错误信息保存在,clean.error
1. urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login_in),
url(r'^register/', views.register),
]
2. views
from .forms import *
def register(request):
if request.is_ajax():
# 通过from表单验证
print(request.POST)
regForm = RegForm(request,request.POST)
regResponse = {'user':None,'errors':None}
if regForm.is_valid():
# 通过验证,可以注册
data = regForm.cleaned_data # 合法的表单数据,是以字典形式保存
user = data.get('user')
pwd = data.get('pwd')
email = data.get('email')
avatar_img = request.FILES.get('valid_img') #获取的文件对象
print(avatar_img)
print(type(avatar_img))
# user_obj = UserInfo.objects.filter(nid=2).update(avatar=avatar_img)
user_obj = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_img)
regResponse['user'] = user_obj.username
else:
regResponse['errors'] = regForm.errors # regForm.errors 保存所有错误信息,包括__all__全局钩子错误
return JsonResponse(regResponse) regForm = RegForm(request) # 前端渲染,虽然没有数据,但是会渲染出标签来
return render(request,'register.html',{'regForm':regForm})
3. reg.html
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form>
{% csrf_token %}
<div class="form-group">
<label for="user">用户名:</label>
{# <input type="text" class="form-control" id="user" placeholder="User">#}
{{ regForm.user }} <span></span>
</div> <div class="form-group">
<label for="pwd">密码:</label>
{# <input type="password" class="form-control" id="pwd" placeholder="Password">#}
{{ regForm.pwd }} <span></span>
</div> <div class="form-group">
<label for="repeat_pwd">确认密码:</label>
{# <input type="password" class="form-control" id="repeat_pwd" placeholder="Repeat Password">#}
{{ regForm.repeat_pwd }} <span></span>
</div> <div class="form-group">
<label for="email">邮箱:</label>
{# <input type="email" class="form-control" id="email" placeholder="Email">#}
{{ regForm.email }} <span></span>
</div>
<div class="row">
<div class="col-md-6">
<input type="button" value="confirm register" class="btn btn-primary regBtn">
</div>
</div> </form> </div>
</div>
</div> <script>
{# AJAX提交注册表单,注册用户 #}
$(".regBtn").click(function () { var $formData = new FormData(); $formData.append('user',$('#id_user').val());
$formData.append('pwd',$('#id_pwd').val());
$formData.append('repeat_pwd',$('#id_repeat_pwd').val());
$formData.append('email',$('#id_email').val());
$formData.append('valid_code',$('#id_valid_code').val());
var file = $('#avatar_file')[0].files[0];
$formData.append('valid_img',file);
$formData.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val()); $.ajax({
url: "/register/",
type: "POST",
data: $formData,
processData:false, // 不做转码或预处理
contentType:false, // 文件类型不做处理
success: function (data) {
if (data.user) {
location.href = '/login/'
}
else {
$('span').html('');
$(".form-group").removeClass("has-error");
console.log(data.errors); $.each(data.errors,function (i,j) {
$("#id_" + i).next().addClass('pull-right').css('color', 'red').html(j[0]).parent().addClass('has-error');
if(i == "__all__") {
$("#id_repeat_pwd").next().addClass("pull-right").css("color", "red").html(j[0]).parent().addClass("has-error");
$("#id_pwd").parent().addClass("has-error");
}
})
}
}
})
})
</script>
form表单使用(博客系统的登陆验证,注册)的更多相关文章
- 26种基于PHP的开源博客系统
26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...
- 使用js提交form表单的两种方法
提交form表单的时候瑶族一些简单的验证,验证完后才能提交,避免无效提交. 1.当输入用户名和密码为空的时候,需要判断.这时候就用到了校验用户名和密码,这个需要在前端页面写:有两种方法,一种是用sub ...
- element-ui Form表单验证
element-ui Form表单验证规则全解 element的form表单非常好用,自带了验证规则,用起来很方便,官网给的案例对于一些普通场景完全没问题,不过一些复杂场景的验证还得自己多看文档摸索, ...
- 2.1博客系统 |基于form组件和Ajax实现注册登录
基于forms组件和Ajax实现注册功能 1 基于forms组件设计注册页面 --点击头像 === 点击input --头像预览: 修改用户选中的文件对象:获取文件对象的路径:修改img的src属性, ...
- 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文
一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...
- 【django之博客系统开发】
一.项目简介 使用django开发一套博客系统,参考博客园. 需求如下: 项目结构: 二.全部代码 from django.db import models # Create your models ...
- Django完整的开发一个博客系统
今天花了一些时间搭了一个博客系统,虽然并没有相关于界面的美化,但是发布是没问题的. 开发环境 操作系统:windows 7 64位 Django: 1.96 Python:2.7.11 IDE: Py ...
- web开发-Django博客系统
项目界面图片预览 项目代码github地址 项目完整流程 项目流程: 1 搞清楚需求(产品经理) (1) 基于用户认证组件和Ajax实现登录验证(图片验证码) (2) 基于forms组件和Ajax实现 ...
- PHP个人博客系统开发历程
声明: Author:GenialX GenialX's QQ:2252065614 GenialX's URL:胡旭博客 - www.ihuxu.com 一年多曾经的某一天,我在上交实验报告时,偶然 ...
随机推荐
- EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- 在windows x64上部署使用Redis
一.下载Redis 下载地址:https://github.com/MSOpenTech/redis/releases 二.安装Redis 将下载文件解压到D:\redis 后,可见: 三.启动Red ...
- 【Python】序列的方法
任何序列都可以引用其中的元素(item). 下面的内建函数(built-in function)可用于列表(表,定值表,字符串) #s为一个序列 len(s) 返回: 序列中包含元素的个数 min(s ...
- iOS自动化探索(一)WebDriverAgent安装
WebDriverAgent FaceBook推出的一款iOS移动测试框架, 支持真机和模拟器, 同时支持USB, 官方是这样介绍的: https://github.com/facebook/WebD ...
- softmax回归(理论部分解释)
前面我们已经说了logistic回归,训练样本是,(且这里的是d维,下面模型公式的x是d+1维,其中多出来的一维是截距横为1,这里的y=±1也可以写成其他的值,这个无所谓不影响模型,只要是两类问题就可 ...
- 使用vue遇到坑
1.请求ajax方式一定要在Vue methods或creads里去请求. 方便做下拉刷新数据 . 2.多看看vue源码. 3.多写tab常项,h5下拉滚动,pc分页效果,回到顶部,提高熟悉vue需求 ...
- 如何将桌面的路径定义到其它盘符,如d:\users\桌面
首先要在“开始”——“运行”内输入“regedit”打开注册表编辑器,然后要在“文件”下拉菜单中的“导出”功能备份好注册表,以防万一,接着在左侧窗口依次打开: HKEY_CURRENT_USER\So ...
- Linux中查看各文件夹大小命令:du -h --max-depth=1
Linux中查看各文件夹大小命令:du -h --max-depth=1 du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-siz ...
- Qt中QT_BEGIN_NAMESPACE和QT_END_NAMESPACE的作用
在Qt中,我们经常会看到 QT_BEGIN_NAMESPACE class QAction; class QMenu; class QPlainTextEdit; QT_END_NAMESPACE 这 ...
- 在Linux上部署DotNet Core项目的时候发现Apache无法转发Kestrel的5000端口的问题
CentOS服务器上使用Apache托管Dotnet Core2,服务启动了,端口也打开了.在本地使用curl命令可以访问5000端口的网页内容,但是访问Apache的端口却无法获取到网页的内容.想起 ...