3- 功能2:基于forms组件和ajax实现注册功能

1、forms组件的注册页面

3- 功能2:基于forms组件和ajax实现注册功能

url

from django.urls import path, re_path
from blog import views
from django.views.static import serve
from cnblog import settings urlpatterns = [
re_path('^login/$', views.login, name='login'),
re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
re_path('^index/$', views.index, name='index'),
re_path('^register/$', views.register, name='register'),
]

views视图

from blog.myForms import UserForm  # froms组件

def register(request):
"""
注册页面
:param request:
:return:
""" form = UserForm return render(request, "blog/register.html", {'form':form})

forms组件

from django import forms
from django.forms import widgets
from blog.models import UserInfo
from django.core.exceptions import ValidationError class UserForm(forms.Form):
user = forms.CharField(max_length=32,label="用户名",
error_messages={"required": "该字段不能为空"},
widget=widgets.TextInput(attrs={"class": "form-control"}))
pwd = forms.CharField(max_length=32, label="密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
re_pwd = forms.CharField(max_length=32, label="确认密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
email = forms.EmailField(max_length=32, label="邮箱",
widget=widgets.EmailInput(attrs={"class": "form-control"}))

模板层

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
<script src="/static/js/jquery-3.2.1.min.js"></script>
</head>
<body> <h3>注册页面</h3> <div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<form>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %} <div class="form-group">
<label for="">头像</label>
<img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
style="margin-left: 20px">
<input type="file" id="avatar">
</div> <input type="button" class="btn btn-success register-btn" value="注册">
</form>
</div>
</div>
</div>
</body> </html>

2、头像上传,预览功能

3- 功能2:基于forms组件和ajax实现注册功能

(1)label标签的for属性

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

  (2)头像图像,上传文件input框,一致

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

  (3)头像预览功能:获取input框的图片

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
<script src="/static/js/jquery-3.2.1.min.js"></script>
</head>
<body> <h3>注册页面</h3> <div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<form>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.auto_id }}">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %} <div class="form-group">
<label for="avatar">头像 <img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
style="margin-left: 20px">
<input type="file" id="avatar" style="display: none"> </label>
</div> <input type="button" class="btn btn-success register-btn" value="注册">
</form>
</div>
</div>
</div> <script type="text/javascript">
$(function () {
$('#avatar').change(function () {
//获取用户选中的文件对象
var file_obj = $(this)[0].files[0]; //获取文件对象的路径
var reader = new FileReader();
reader.readAsDataURL(file_obj); //修改img的src属性, src= 文件对象的路径
// $(this).prepend('img').attr("src", reader.result); // 等页面加载完成在执行onload
reader.onload = function () {
$("#avatar_img").attr("src", reader.result)
}
})
})
</script>
</body> </html>

3、Ajax提交formdata数据

(1)点击注册按钮

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

 注册视图

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

  (2)循环展示错误msg

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

  (3)代码优化:form表单数据序列化append

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

4、forms组件的局部钩子,全局钩子

3- 功能2:基于forms组件和ajax实现注册功能

  3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

5、注册成功,添加数据

(1)模板层 跳转到view视图

3- 功能2:基于forms组件和ajax实现注册功能

  (2)view视图层

3- 功能2:基于forms组件和ajax实现注册功能

  (3)FieldFile字段

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

  数据库保存的是文件的路径

  3- 功能2:基于forms组件和ajax实现注册功能3- 功能2:基于forms组件和ajax实现注册功能

  (2)代码优化

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

6、media配置

Dajngo有两种静态文件:

     /static/    :  js,css,img
/media/ : 用户上传文件

  

settings配置

# MEDIA配置:与用户上传相关的配置
# 配置1:用户上传头像的文件
MEDIA_ROOT = os.path.join(BASE_DIR, "media") # 配置2:开放media目录给用户
MEDIA_URL = "/media/"

  

配置1:settings配置media目录

3- 功能2:基于forms组件和ajax实现注册功能    3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

 配置2:开放media目录给用户

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

(3)开放给用户的目录

开放给用户的目录
http://127.0.0.1:8000/static/img/default.jpg
http://127.0.0.1:8000/blog/media/avatars/mingren.jpg/

3- 功能2:基于forms组件和ajax实现注册功能

3- 功能2:基于forms组件和ajax实现注册功能

7、完整代码

主url

from django.contrib import admin
from django.urls import path, re_path, include urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^blog/', include(('blog.urls', 'blog')))
]

url

from django.urls import path, re_path
from blog import views
from django.views.static import serve
from cnblog import settings urlpatterns = [
re_path('^login/$', views.login, name='login'),
re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
re_path('^index/$', views.index, name='index'),
re_path('^register/$', views.register, name='register'), # media配置
re_path(r'^media/(?P<path>.*)/$', serve, {"document_root": settings.MEDIA_ROOT}),
]

注册views视图

from django.shortcuts import render, HttpResponse, redirect
from blog.utils.validCode import get_validCode_img # 导入验证码函数
from django.http import JsonResponse # Json数据返回到前端
from django.contrib import auth # 用户认证组件
from blog.models import UserInfo
from blog.myForms import UserForm # froms组件 def register(request):
"""
注册页面
:param request:
:return:
"""
# if request.method == 'POST':
if request.is_ajax():
response = {'user':None, "msg":None} form = UserForm(request.POST)
if form.is_valid():
response['user'] = form.cleaned_data.get("user") # 生成一条数据
user = request.POST.get("user")
pwd = request.POST.get("pwd")
email = request.POST.get("email")
avatar_obj = request.FILES.get("avatar")
print(avatar_obj) extra_fields = {}
if avatar_obj:
extra_fields["avatar"] = avatar_obj UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra_fields) """
if avatar_obj:
# 快捷键 alt + f7
UserInfo.objects.create_user(username=user, password=pwd, email=email, avatar=avatar_obj)
else:
UserInfo.objects.create_user(username=user, password=pwd, email=email)
""" else:
print(form.cleaned_data)
print(form.errors)
response['msg'] = form.errors return JsonResponse(response) form = UserForm return render(request, "blog/register.html", {'form':form})

注册forms组件

from django import forms
from django.forms import widgets
from blog.models import UserInfo
from django.core.exceptions import ValidationError class UserForm(forms.Form):
user = forms.CharField(max_length=32,label="用户名",
error_messages={"required": "该字段不能为空"},
widget=widgets.TextInput(attrs={"class": "form-control"}))
pwd = forms.CharField(max_length=32, label="密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
re_pwd = forms.CharField(max_length=32, label="确认密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
email = forms.EmailField(max_length=32, label="邮箱",
widget=widgets.EmailInput(attrs={"class": "form-control"})) # 用户名的认证
def clean_user(self):
user = self.cleaned_data.get('user') user_obj = UserInfo.objects.filter(username=user).first()
if not user_obj:
return user
else:
raise ValidationError('该用户名已经注册')
# return ValidationError('该用户名已经注册') # 不能用出现bug # 密码
def clean(self):
pwd = self.cleaned_data.get("pwd")
re_pwd = self.cleaned_data.get("re_pwd") if pwd and re_pwd:
if pwd == re_pwd:
return self.cleaned_data
else:
# return ValidationError("两次密码不一致!")
raise ValidationError("两次密码不一致!")
else:
return self.cleaned_data

注册页面模板层

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
<script src="/static/js/jquery-3.2.1.min.js"></script>
</head>
<body> <h3>注册页面</h3> <div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<form id="id_form">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.auto_id }}">{{ field.label }}</label>
{{ field }}
<span class="error pull-right" style="color: red"></span>
</div>
{% endfor %} <div class="form-group">
<label for="avatar">头像 <img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
style="margin-left: 20px">
<input type="file" id="avatar" style="display: none"> </label>
</div> <input type="button" class="btn btn-success register-btn" value="注册">
</form>
</div>
</div>
</div> </body> </html>

注册页面js代码

<script type="text/javascript">
$(function () {
$('#avatar').change(function () {
//获取用户选中的文件对象
var file_obj = $(this)[0].files[0]; //获取文件对象的路径
var reader = new FileReader();
reader.readAsDataURL(file_obj); //修改img的src属性, src= 文件对象的路径
// $(this).prepend('img').attr("src", reader.result); // 等页面加载完成在执行onload
reader.onload = function () {
$("#avatar_img").attr("src", reader.result)
}
})
}); //基于ajax提交数据
$(function () {
$('.register-btn').click(function () { //获取数据
var formdata = new FormData();
<!--
formdata.append("user", $('#id_user').val());
formdata.append("pwd", $('#id_pwd').val());
formdata.append("re_pwd", $('#id_re_pwd').val());
formdata.append("email", $('#id_email').val());
formdata.append("csrfmiddlewaretoken", $('[name="csrfmiddlewaretoken"]').val());
-->
var request_data = $('#id_form').serializeArray();
$.each(request_data, function (index, data) {
formdata.append(data.name, data.value)
}); formdata.append("avatar", $("#avatar")[0].files[0]); $.ajax({
url: '',
type: 'post',
contentType: false,
processData: false,
data: formdata,
success: function (data) {
console.log(data);
if (data.user) { //注册成功
location.href = "/blog/login" } else {
//清空错误信息,和div的样式
$('span.error').html("");
$(".form-group").removeClass("has-error"); //展示error_msg
$.each(data.msg, function (field, error_list) {
if (field == "__all__") {
$('#id_re_pwd').next('span').html(error_list[0]).parent('div').addClass('has-error'); } else {
$('#id_' + field).next('span').html(error_list[0]).parent('div').addClass('has-error'); }
}) } }
})
})
}) </script>

8、总结

基于forms组件和Ajax实现注册功能

# 1 基于forms组件设计注册页面

   ---点击头像===点击input

   ---头像预览:
1 获取用户选中的文件对象
2 获取文件对象的路径
3 修改img的src属性 ,src=文件对象的路径 # 2 错误信息: views: form.erorrs # {"user":[......]} Ajax.success:
$.each(data.msg, function (field, error_list) { $("#id_" + field).next().html(error_list[0]);
$("#id_" + field).parent().addClass("has-error"); }) # 3 局部钩子和全局钩子校验
user字段不能重复
两次密码不一致 # 4 FileField与ImageFiled class UserInfo(AbstractUser): nid = models.AutoField(primary_key=True)
telephone = models.CharField(max_length=11, null=True, unique=True)
avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") avatar_obj=request.FILES.get("avatar")
user_obj=UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_obj) Dajngo实现: 会将文件对象下载到项目的根目录中avatars文件夹中(如果没有avatar文件夹,Django会自动创建),user_obj的avatar存的是文件的相对路径。 # 5 Media 配置之MEDIA_ROOT: Dajngo有两种静态文件: /static/ : js,css,img
/media/ : 用户上传文件 class UserInfo(AbstractUser): nid = models.AutoField(primary_key=True)
telephone = models.CharField(max_length=11, null=True, unique=True)
avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") avatar_obj=request.FILES.get("avatar")
user_obj=UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_obj) 一旦配置了
MEDIA_ROOT=os.path.join(BASE_DIR,"media") Dajngo实现: 会将文件对象下载到MEDIA_ROOT中avatars文件夹中(如果没有avatar文件夹,Django会自动创建),user_obj的avatar存的是文件的相对路径。 # 6 Media 配置之MEDIA_URl: 浏览器如何能直接访问到media中的数据 settings.py:
MEDIA_URL="/media/" urls.pt:
# media配置:
re_path(r"media/(?P<path>.*)$",serve,{"document_root":settings.MEDIA_ROOT})
上一篇:MySQL几种方法的数据库备份


下一篇:ES按资源类型统计个数