张家港做网站多少钱,怎么看一个网站用什么做的,手机版商城网站都有哪 些功能,重庆网站搭建1 注册功能 1.1 注册功能form组件 1.2 注册功能前端 1.3 注册功能后端 1.4 forms组件和前后端总结 2 登录功能 2.1 登录前端 2.2 生成验证码 1 注册功能 1.1 注册功能form组件
# 注册页面-用户名-密码-确认密码-邮箱-手机号-头像# form组件 可以帮助我们1 快速生成前端页面2 数…1 注册功能 1.1 注册功能form组件 1.2 注册功能前端 1.3 注册功能后端 1.4 forms组件和前后端总结 2 登录功能 2.1 登录前端 2.2 生成验证码 1 注册功能 1.1 注册功能form组件
# 注册页面-用户名-密码-确认密码-邮箱-手机号-头像# form组件 可以帮助我们1 快速生成前端页面2 数据校验3 错误处理# 如何使用-1 写一个类继承forms.Form-2 在类中写属性和方法-属性要跟咱们要校验或自动生成页面的字段一一对应-方法对字段进行校验clean_字段名 给单个字段校验clean 给多个字段校验-3 在视图函数中使用-4 模板中使用# form表单中如果定义了button或input 类型是submit只要点击就会默认触发form表单的提交如果我们又写了ajax提交就会触发两次---》导致问题--把它搞外面-input 类型是buttonfrom django import forms
from django.forms import widgets, ValidationError
from .models import UserInfoclass RegisterForm(forms.Form):# max_length18 最长 18# min_length3 最短 3# requiredTrue 必填username forms.CharField(max_length18, min_length3, requiredTrue,label用户名,error_messages{required: 用户名字段必填,max_length: 长度不能超过18,min_length: 最短3}, widgetwidgets.TextInput(attrs{class: form-control}))password forms.CharField(max_length18, min_length3, requiredTrue,label密码,error_messages{required: 用户名字段必填,max_length: 长度不能超过18,min_length: 最短3}, widgetwidgets.PasswordInput(attrs{class: form-control}))re_password forms.CharField(max_length18, min_length3, requiredTrue,label确认密码,error_messages{required: 用户名字段必填,max_length: 长度不能超过18,min_length: 最短3}, widgetwidgets.PasswordInput(attrs{class: form-control}))email forms.EmailField(max_length18, min_length3, requiredTrue,label邮箱,error_messages{required: 用户名字段必填,max_length: 长度不能超过18,min_length: 最短3}, widgetwidgets.EmailInput(attrs{class: form-control}))phone forms.CharField(max_length11, min_length11, requiredTrue,label手机号,error_messages{required: 用户名字段必填,max_length: 长度不能超过11,min_length: 必须11为}, widgetwidgets.TextInput(attrs{class: form-control}))# 方法名只能写两类# 一类是 clean_字段名 校验单个字段def clean_username(self): # 如果能走到这里说明上面的校验已经通过了校验过后的数据都放在一个字典中---》cleaned_datausername self.cleaned_data.get(username)# 用户名不能以sb开头if username.startswith(sb):# 校验不通过抛异常raise ValidationError(名字不能以sb开头)# 如果用户名存在也不能注册了res UserInfo.objects.filter(usernameusername).exists()if res:raise ValidationError(该用户已经存在)return username# 二类是 clean 同时校验多个字段def clean(self):password self.cleaned_data.get(password)re_password self.cleaned_data.get(re_password)if not password re_password:raise ValidationError(两次密码不一致)return self.cleaned_data 1.2 注册功能前端
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlescript src/static/js/jquery.min.js/scriptlink relstylesheet href/static/bootstrap/css/bootstrap.min.css
/head
bodydiv classcontainer-fluiddiv classrowdiv classcol-md-6 col-md-offset-3h1 classtext-center注册功能/h1form idregister_form{% csrf_token %}{% for foo in form %}div classform-grouplabel for{{ foo.auto_id }}{{ foo.label }}/label{{ foo }} span classpull-right error stylecolor: red/span/div{% endfor %}div classform-grouplabel forid_avatar头像img src/static/img/default.png alt height80px width80px idid_imgstylemargin-left: 20px/labelinput typefile idid_avatar classform-control acceptimage/* styledisplay: none/divdiv classtext-centerinput typebutton value注册 classbtn btn-danger idid_submitspan classerror stylecolor: darkred;margin-left: 10px idid_error/span/div/form/div/div
/div/bodyscript// 1 监控文件变化$(#id_avatar).change(function () {// 读出input 的图片写到 img标签上// 需要借助于文件阅读器var fileReader new FileReader();// 把文件对象读入文件阅读器中fileReader.readAsDataURL($(#id_avatar)[0].files[0])// 等文件读完再放入fileReader.onload function () {//$(#id_img).attr(height, 300px)$(#id_img).attr(src, fileReader.result)//$(#id_img)[0].src fileReader.result}})// 2 按钮提交---》注册功能$(#id_submit).click(function () {var formdata new FormData()// 把文件放入formdata.append(my_img, $(#id_avatar)[0].files[0])//放数据用户名密码确认密码手机号邮箱 你可以一个个放---笨办法/*formdata.append(username, $(#id_username).val())formdata.append(password, $(#id_password).val())formdata.append(re_password, $(#id_re_password).val())formdata.append(phone, $(#id_phone).val())formdata.append(email, $(#id_email).val())formdata.append(csrfmiddlewaretoken, {{ csrf_token }}) // csrf 的token*/// 简单方案var register_form $(#register_form).serializeArray() // 会把当前form表单中得数据放到列表套字典的形式/*数组[{name:xx,value:yy}, {…}, {…}, {…}, {…}]*///console.log(register_form)// jq 的循环$.each(register_form, function (i, v) {//console.log(v[name])//console.log(v[value])formdata.append(v[name], v[value])})$.ajax({url: /register/,method: post,processData: false,contentType: false,data: formdata,success: function (data) {if (data.code 100) {location.href /login/} else { // 不成功// 两次密码不一致把错误写在 注册按钮后面// input 自己的错误写在自己后面// 循环返回的错误$.each(data.errors, function (key, value) {if (key __all__) {$(#id_error).html(value[0])}$(#id_ key).next().html(value[0]).parent().addClass(has-error)})// 过3s后清空错误和红框setTimeout(function () {$(.error).html().parent().removeClass(has-error)//alert(asfdsdaf)}, 3000)}}})})// 3 当用户名输入框失去焦点我们就去后端校验用户名是否注册过$(#id_username).blur(function () {//alert(失去焦点了)//var username$(#id_username).val()var username $(this).val()$.ajax({url: /check_username/?username username,method: get,success: function (data) {console.log(data)if (data.code ! 100) {// 1 清空输入框//$(this).val()// 2 错误提示//$(this).next().html(data.msg)console.log(ssss)// 两句可以并做一句---》链式调用// 如果在另一个内部函数中就不能用this//var ss$(#id_username).val()//$(#id_username).next().html(data.msg).parent().addClass(has-error).children(input).val()$(#id_username).val().next().html(data.msg).parent().addClass(has-error)}}})})/script
/html1.3 注册功能后端
from django.shortcuts import render
from .forms import RegisterForm
from .models import UserInfo
from django.http import JsonResponsedef register(request):if request.method GET:form RegisterForm()return render(request, register.html, {form: form})else:# # 1 数据# print(request.POST)# # 2 文件# print(request.FILES.get(my_img))# 取出头像avatar request.FILES.get(my_img)# 校验数据是否合法username: adminpassword: 123email: anqq.comphone: 12345678935avatar:文件form RegisterForm(request.POST) # 使用form校验传入的数据if form.is_valid(): # 校验通过# 保存data form.cleaned_data# 把re_password 弹出data.pop(re_password)# 把头像加入if avatar:data[avatar] avatarUserInfo.objects.create_user(**data)return JsonResponse({code: 100, msg: 注册成功})else:return JsonResponse({code: 101, msg: 注册失败, errors: form.errors})# 校验用户名是否存在的接口
def check_username(request):username request.GET.get(username)res UserInfo.objects.filter(usernameusername).exists()if res:# 约定状态码100表示成功非100表示失败return JsonResponse({code: 101, msg: 用户已经存在})return JsonResponse({code: 100, msg: 您可以注册})1.4 forms组件和前后端总结
# 1 forms组件-1 渲染模板-2 校验数据-3 渲染错误- formRegisterForm()---渲染页面- formRegisterForm(requets.POST)---校验数据
# 2 取数据取文件-form-data提交数据-request.POST 中取数据-request.FILES.get(名字) 取文件-补前端是keyvalue 后端变成了 key:[value]-request.data 不是真正的字典{username: [admin,xxx], password: [123]}request.POST.get(username)request.POST.getlist(username)# 3 保存 文件和数据# data 是form校验过后的数据没有头像data.pop(re_password) # 不是表的字段# 把头像加入 头像是表的字段if avatar:data[avatar] avatar # 文件对象# avatar models.ImageField(upload_toavatar, defaultavatar/default.png)内部自动打开一个空文件把文件写入到空文件中 【/media/avatar/】,并且把路径赋值给avatar数据库字段UserInfo.objects.create_user(**data)# 4 前端头像实时显示-隐藏了 input file---》input只能接收图片类型-只要input发生变化change---》把图片读出来写入到 img标签中var fileReader new FileReader();fileReader.readAsDataURL($(#id_avatar)[0].files[0])fileReader.onload function () {$(#id_img).attr(src, fileReader.result)}# 5 用户名失去焦点(blur)---》向后端校验# 6 form表单使用var register_form $(#register_form).serializeArray() 转到数组中# 7 $.each(可以被循环的,function(){})# 8 错误信息渲染-__all__ 全局错误---》显示在注册后面if (key __all__) {$(#id_error).html(value[0])}-其他错误显示在自己后面$(#id_ key).next().html(value[0]).parent().addClass(has-error)-定时任务3s后干什么setTimeout(function () {$(.error).html().parent().removeClass(has-error)}, 3000)2 登录功能 2.1 登录前端
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlescript src/static/js/jquery.min.js/scriptlink relstylesheet href/static/bootstrap/css/bootstrap.min.css
/head
bodydiv classcontainer-fluiddiv classrowdiv classcol-md-6 col-md-offset-3h1 classtext-center登录功能/h1formdiv classform-grouplabel for用户名/labelinput typetext nameusername classform-control/divdiv classform-grouplabel for密码/labelinput typetext namepassword classform-control/divdiv classform-grouplabel for验证码/labeldiv classrowdiv classcol-md-6input typetext namecode classform-control/divimg src/get_code/ alt classcol-md-6 height35/div/divdiv classtext-center stylemargin-top: 50pxinput typebutton value登录 classbtn btn-danger idid_submitspan classerror stylecolor: darkred;margin-left: 10px idid_error/span/div/form/div/div
/div/body/html2.2 生成验证码
# 第三方方案
https://pythonjishu.com/ljpdvvedzkqiovs/# 自己的方案
def get_code(request):# 前端显示图片 方式一# with open(./static/img/4.jpg, rb) as f:# data f.read()# return HttpResponse(data)# 方式二自己生成一张图片保存到本地--打开返回给前端# image_tmp Image.new(RGB, (300, 38), (255, 255, 0))## with open(code.png, wb) as f:# image_tmp.save(f, png)## with open(code.png, rb) as f:# data f.read()# return HttpResponse(data)# 方式三借助于ByteIo把文件内容放在内存中# image_tmp Image.new(RGB, (300, 38), (0, 255, 0))# # 放在内存中# my_io BytesIO()# image_tmp.save(my_io, png)# return HttpResponse(my_io.getvalue())# 方式四 要在图片上写文字# image_tmp Image.new(RGB, (300, 38), (0, 255, 0))# # 把空图片放在了画板上# draw ImageDraw.Draw(image_tmp)# draw.text((0, 0), lqz)# my_io BytesIO()# image_tmp.save(my_io, png)# return HttpResponse(my_io.getvalue())# 方式5 加入字体文件# image_tmp Image.new(RGB, (300, 38), (0, 255, 0))# # 把空图片放在了画板上# draw ImageDraw.Draw(image_tmp)# # 加入字体# img_font ImageFont.truetype(./static/font/xgdl.ttf, 23)# draw.text((0, 0), 西瓜大朗, fill(0, 0, 128), fontimg_font, )# my_io BytesIO()# image_tmp.save(my_io, png)# return HttpResponse(my_io.getvalue())# 方式6 随机生成 5 大小写字母和数字图片背景色和字的颜色每次不一样image_tmp Image.new(RGB, (300, 38), (0, 255, 0))# 把空图片放在了画板上draw ImageDraw.Draw(image_tmp)# 加入字体img_font ImageFont.truetype(./static/font/xgdl.ttf, 23)draw.text((0, 0), 西瓜大朗, fill(0, 0, 128), fontimg_font, )my_io BytesIO()image_tmp.save(my_io, png)return HttpResponse(my_io.getvalue())import randomdef get_random_code():code for i in range(5):# 随机生成一个大写字母upper_char chr(random.randint(65, 90))low_char chr(random.randint(97, 122))num_char str(random.randint(0, 9))res random.choice([upper_char, low_char, num_char])code resreturn codeif __name__ __main__:print(get_random_code()) 文章转载自: http://www.morning.lhxdq.cn.gov.cn.lhxdq.cn http://www.morning.yqjjn.cn.gov.cn.yqjjn.cn http://www.morning.plnry.cn.gov.cn.plnry.cn http://www.morning.nqnqz.cn.gov.cn.nqnqz.cn http://www.morning.xxrgt.cn.gov.cn.xxrgt.cn http://www.morning.frtb.cn.gov.cn.frtb.cn http://www.morning.zylrk.cn.gov.cn.zylrk.cn http://www.morning.pcxgj.cn.gov.cn.pcxgj.cn http://www.morning.qkkmd.cn.gov.cn.qkkmd.cn http://www.morning.bphqd.cn.gov.cn.bphqd.cn http://www.morning.ktskc.cn.gov.cn.ktskc.cn http://www.morning.nxbsq.cn.gov.cn.nxbsq.cn http://www.morning.jfcbz.cn.gov.cn.jfcbz.cn http://www.morning.htsrm.cn.gov.cn.htsrm.cn http://www.morning.wmsgt.cn.gov.cn.wmsgt.cn http://www.morning.zwgbz.cn.gov.cn.zwgbz.cn http://www.morning.nqgds.cn.gov.cn.nqgds.cn http://www.morning.gfqjf.cn.gov.cn.gfqjf.cn http://www.morning.playmi.cn.gov.cn.playmi.cn http://www.morning.gccdr.cn.gov.cn.gccdr.cn http://www.morning.fkdts.cn.gov.cn.fkdts.cn http://www.morning.hgwsj.cn.gov.cn.hgwsj.cn http://www.morning.pfnwt.cn.gov.cn.pfnwt.cn http://www.morning.rqbr.cn.gov.cn.rqbr.cn http://www.morning.jcwrb.cn.gov.cn.jcwrb.cn http://www.morning.hjjhjhj.com.gov.cn.hjjhjhj.com http://www.morning.wqhlj.cn.gov.cn.wqhlj.cn http://www.morning.qhtlq.cn.gov.cn.qhtlq.cn http://www.morning.lwqst.cn.gov.cn.lwqst.cn http://www.morning.bfcrp.cn.gov.cn.bfcrp.cn http://www.morning.ghslr.cn.gov.cn.ghslr.cn http://www.morning.qmwzr.cn.gov.cn.qmwzr.cn http://www.morning.fllx.cn.gov.cn.fllx.cn http://www.morning.jiuyungps.com.gov.cn.jiuyungps.com http://www.morning.pyxtn.cn.gov.cn.pyxtn.cn http://www.morning.cjmmn.cn.gov.cn.cjmmn.cn http://www.morning.zkrzb.cn.gov.cn.zkrzb.cn http://www.morning.rcjyc.cn.gov.cn.rcjyc.cn http://www.morning.nlkjq.cn.gov.cn.nlkjq.cn http://www.morning.nshhf.cn.gov.cn.nshhf.cn http://www.morning.lnrr.cn.gov.cn.lnrr.cn http://www.morning.yfstt.cn.gov.cn.yfstt.cn http://www.morning.nwtmy.cn.gov.cn.nwtmy.cn http://www.morning.hqbk.cn.gov.cn.hqbk.cn http://www.morning.hqbk.cn.gov.cn.hqbk.cn http://www.morning.zbjfq.cn.gov.cn.zbjfq.cn http://www.morning.nzqqd.cn.gov.cn.nzqqd.cn http://www.morning.txrq.cn.gov.cn.txrq.cn http://www.morning.wjlnz.cn.gov.cn.wjlnz.cn http://www.morning.fwlch.cn.gov.cn.fwlch.cn http://www.morning.bpmdr.cn.gov.cn.bpmdr.cn http://www.morning.smwlr.cn.gov.cn.smwlr.cn http://www.morning.rbbyd.cn.gov.cn.rbbyd.cn http://www.morning.zljqb.cn.gov.cn.zljqb.cn http://www.morning.mgskc.cn.gov.cn.mgskc.cn http://www.morning.qxlhj.cn.gov.cn.qxlhj.cn http://www.morning.rwls.cn.gov.cn.rwls.cn http://www.morning.lmhh.cn.gov.cn.lmhh.cn http://www.morning.prgrh.cn.gov.cn.prgrh.cn http://www.morning.llfwg.cn.gov.cn.llfwg.cn http://www.morning.gwkjg.cn.gov.cn.gwkjg.cn http://www.morning.fhsgw.cn.gov.cn.fhsgw.cn http://www.morning.plcyq.cn.gov.cn.plcyq.cn http://www.morning.mxlmn.cn.gov.cn.mxlmn.cn http://www.morning.wgtnz.cn.gov.cn.wgtnz.cn http://www.morning.shuanga.com.cn.gov.cn.shuanga.com.cn http://www.morning.pftjj.cn.gov.cn.pftjj.cn http://www.morning.khtjn.cn.gov.cn.khtjn.cn http://www.morning.lffrh.cn.gov.cn.lffrh.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.kchwr.cn.gov.cn.kchwr.cn http://www.morning.xknmn.cn.gov.cn.xknmn.cn http://www.morning.ymjgx.cn.gov.cn.ymjgx.cn http://www.morning.dbdmr.cn.gov.cn.dbdmr.cn http://www.morning.jgmlb.cn.gov.cn.jgmlb.cn http://www.morning.ylph.cn.gov.cn.ylph.cn http://www.morning.tkflb.cn.gov.cn.tkflb.cn http://www.morning.lnckq.cn.gov.cn.lnckq.cn http://www.morning.gtmgl.cn.gov.cn.gtmgl.cn http://www.morning.ykrss.cn.gov.cn.ykrss.cn