一、博客系统得表关系

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser 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')
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self):
return self.username class Blog(models.Model):
"""
博客信息
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='个人博客标题', max_length=64)
site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True)
theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self):
return self.title class Category(models.Model):
"""
博主个人文章分类表
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='分类标题', max_length=32)
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self):
return self.title class Tag(models.Model):
"""
博主个人文章标签表
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='标签名称', max_length=32)
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self):
return self.title class Article(models.Model):
"""
文章信息
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=50, verbose_name='文章标题')
desc = models.CharField(max_length=255, verbose_name='文章描述')
create_time = models.DateTimeField(verbose_name='创建时间')
category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField(
to='Tag',
through='Article2Tag',
through_fields=('article','tag'),
) def __str__(self):
return self.title class ArticleDetail(models.Model):
"""
文章详细表
"""
nid = models.AutoField(primary_key=True)
content = models.TextField()
article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model):
"""
多对多,文章、标签得第三张表
"""
nid = models.AutoField(primary_key=True)
article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE)
tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid', on_delete=models.CASCADE) class Meta:
unique_together = [
('article', 'tag'),
] def __str__(self):
v = self.article.title + '--' + self.tag.title
return v class ArticleUpDown(models.Model):
"""
点赞,踩灭表
"""
nid = models.AutoField(primary_key=True)
user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE)
article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
is_up = models.BooleanField(default=True) class Meta:
unique_together = [
('article','user'),
] class Comment(models.Model):
"""
评论表
"""
nid = models.AutoField(primary_key=True)
article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
content = models.CharField(verbose_name='评论内容', max_length=255)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE) def __str__(self):
return self.content

操作配置:

AUTH_USER_MODEL = "blog.UserInfo"    

create database cnblog;

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'cnblog',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': 3306,
}
} import pymysql
pymysql.install_as_MySQLdb() Tools/Run manage.py Task
makemigrations
migrate 。。。

结果:

二、基于Ajax和用户登录验证

验证码得获取:

方式一:

 <img width="" height="" src="/get_valid_img/" alt="">
def get_valid_img(request):
# 方式一
with open('girl.jpg','rb') as f:
data = f.read() return HttpResponse(data)

方式二:

def get_valid_img(request):
# 方式二
"""
pip install pillow
"""
import PIL
from PIL import Image import random def get_random_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) f = open('valid_code.png','wb') # 存在磁盘上
image.save(f,'png') f = open('valid_code.png','rb')
data = f.read()
f.close() return HttpResponse(data)

方式三:

def get_valid_img(request):
# 方式三
import PIL
from PIL import Image import random def get_random_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) from io import BytesIO
f = BytesIO() # 在内存中创建一张图片 直接返回
image.save(f,'png') data = f.getvalue() return HttpResponse(data)

方式四:

kumo.ttf

def get_valid_img(request):
# 方式四
import PIL
from PIL import Image,ImageDraw,ImageFont import random def get_random_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) draw = ImageDraw.Draw(image) font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32) temp = []
# 生成5个随机字符
for i in range(5):
random_num = str(random.randint(0,9))
random_low_alpha = chr(random.randint(97,122))
random_upper_alpha = chr(random.randint(65,90)) random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
draw.text((24+i*36,0),random_char,get_random_color(),font=font) # 保存随机数
temp.append(random_char) # 造点 造线 造圆
width = 210
height = 35
for i in range(2):
x1 = random.randint(0,width)
x2 = random.randint(0,width)
y1 = random.randint(0,height)
y2 = random.randint(0,height)
draw.line((x1,y1,x2,y2),fill=get_random_color())
for i in range(2):
draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color())
x = random.randint(0,width)
y = random.randint(0,height)
draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color()) # 在内存中生成图片
from io import BytesIO
f = BytesIO()
image.save(f,'png')
data = f.getvalue()
f.close() valid_str = ''.join(temp)
print('valid_str:',valid_str) request.session['valid_str'] = valid_str return HttpResponse(data)

登录验证:

<body>
<h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3>
</body>
<input type="button" class="btn btn-default login-btn" value="提交">
<span class="error" style="color: red; margin-left: 10px;"></span>
<script src="/static/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$('.login-btn').click(function () {
$.ajax({
url:'',
type:'post',
data:{
csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
user:$('#user').val(),
pwd:$('#pwd').val(),
valid_code:$('#valid_code').val()
},
success:function (data) {
if(data.state){
location.href = '/index/'
}else{
$('.error').text(data.msg) }
} })
})
from django.shortcuts import render,HttpResponse,redirect

from django.http import JsonResponse
from django.contrib import auth def login(request):
if request.is_ajax():
user = request.POST.get('user')
pwd = request.POST.get('pwd')
valid_code = request.POST.get('valid_code') valid_str = request.session.get('valid_str') res = {"state": False, "msg": None}
if valid_code.upper() == valid_str.upper():
user = auth.authenticate(username = user,password = pwd)
if user:
res["state"] = True
auth.login(request, user)
else:
res["msg"] = "username or pwd error"
else:
res["msg"] = "验证码错误" return JsonResponse(res) return render(request,'login.html') def index(request):
if not request.user.username:
return redirect('/login/') return render(request,'index.html')

验证码点击刷新:

 <img id="valid_img" width="" height="" src="/get_valid_img/" alt="">
//验证码点击刷新
$('#valid_img').click(function () {
$(this)[0].src += '?'
})

示例:

from django.db import models
from django.contrib.auth.models import AbstractUser 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')
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self):
return self.username class Blog(models.Model):
"""
博客信息
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='个人博客标题', max_length=64)
site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True)
theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self):
return self.title class Category(models.Model):
"""
博主个人文章分类表
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='分类标题', max_length=32)
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self):
return self.title class Tag(models.Model):
"""
博主个人文章标签表
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(verbose_name='标签名称', max_length=32)
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self):
return self.title class Article(models.Model):
"""
文章信息
"""
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=50, verbose_name='文章标题')
desc = models.CharField(max_length=255, verbose_name='文章描述')
create_time = models.DateTimeField(verbose_name='创建时间')
category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField(
to='Tag',
through='Article2Tag',
through_fields=('article','tag'),
) def __str__(self):
return self.title class ArticleDetail(models.Model):
"""
文章详细表
"""
nid = models.AutoField(primary_key=True)
content = models.TextField()
article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model):
"""
多对多,文章、标签得第三张表
"""
nid = models.AutoField(primary_key=True)
article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE)
tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid', on_delete=models.CASCADE) class Meta:
unique_together = [
('article', 'tag'),
] def __str__(self):
v = self.article.title + '--' + self.tag.title
return v class ArticleUpDown(models.Model):
"""
点赞,踩灭表
"""
nid = models.AutoField(primary_key=True)
user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE)
article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
is_up = models.BooleanField(default=True) class Meta:
unique_together = [
('article','user'),
] class Comment(models.Model):
"""
评论表
"""
nid = models.AutoField(primary_key=True)
article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
content = models.CharField(verbose_name='评论内容', max_length=255)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE) def __str__(self):
return self.content

models.py

from django.shortcuts import render,HttpResponse,redirect

from django.http import JsonResponse
from django.contrib import auth def login(request):
if request.is_ajax():
user = request.POST.get('user')
pwd = request.POST.get('pwd')
valid_code = request.POST.get('valid_code') valid_str = request.session.get('valid_str') res = {"state": False, "msg": None}
if valid_code.upper() == valid_str.upper():
user = auth.authenticate(username = user,password = pwd)
if user:
res["state"] = True
auth.login(request, user)
else:
res["msg"] = "username or pwd error"
else:
res["msg"] = "验证码错误" return JsonResponse(res) return render(request,'login.html') def index(request):
if not request.user.username:
return redirect('/login/') return render(request,'index.html') def get_valid_img(request):
# 方式四
import PIL
from PIL import Image,ImageDraw,ImageFont import random def get_random_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) draw = ImageDraw.Draw(image) font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32) temp = []
# 生成5个随机字符
for i in range(5):
random_num = str(random.randint(0,9))
random_low_alpha = chr(random.randint(97,122))
random_upper_alpha = chr(random.randint(65,90)) random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
draw.text((24+i*36,0),random_char,get_random_color(),font=font) # 保存随机数
temp.append(random_char) # 造点 造线 造圆
width = 210
height = 35
for i in range(2):
x1 = random.randint(0,width)
x2 = random.randint(0,width)
y1 = random.randint(0,height)
y2 = random.randint(0,height)
draw.line((x1,y1,x2,y2),fill=get_random_color())
for i in range(2):
draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color())
x = random.randint(0,width)
y = random.randint(0,height)
draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color()) # 在内存中生成图片
from io import BytesIO
f = BytesIO()
image.save(f,'png')
data = f.getvalue()
f.close() valid_str = ''.join(temp)
print('valid_str:',valid_str) request.session['valid_str'] = valid_str return HttpResponse(data) # 方式三
# import PIL
# from PIL import Image
#
# import random
#
# def get_random_color():
# return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
#
# image = Image.new('RGB',(260,35),get_random_color())
#
# from io import BytesIO
# f = BytesIO() # 在内存中创建一张图片 直接返回
# image.save(f,'png')
#
# data = f.getvalue()
#
# return HttpResponse(data) # 方式二
# """
# pip install pillow
# """
# import PIL
# from PIL import Image
#
# import random
#
# def get_random_color():
# return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
#
# image = Image.new('RGB',(260,35),get_random_color())
#
# f = open('valid_code.png','wb') # 存在磁盘上
# image.save(f,'png')
#
# f = open('valid_code.png','rb')
# data = f.read()
# f.close()
#
# return HttpResponse(data) # 方式一
# with open('girl.jpg','rb') as f:
# data = f.read()
#
# return HttpResponse(data)

views.py

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
<style type="text/css">
.container{ margin-top: 100px;}
</style>
</head>
<body>
<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="Username">
</div> <div class="form-group">
<label for="pwd">密码</label>
<input type="password" class="form-control" id="pwd" placeholder="Password">
</div> <div class="form-group">
<label for="pwd">验证码</label>
<div class="row"> <div class="col-md-6">
<input type="text" class="form-control" id="valid_code">
</div> <div class="col-md-6">
<img id="valid_img" width="260" height="35" src="/get_valid_img/" alt="">
</div>
</div>
</div> <input type="button" class="btn btn-default login-btn" value="提交">
<span class="error" style="color: red; margin-left: 10px;"></span>
</form>
</div>
</div>
</div> <script src="/static/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
//提交
$('.login-btn').click(function () {
$.ajax({
url:'',
type:'post',
data:{
csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
user:$('#user').val(),
pwd:$('#pwd').val(),
valid_code:$('#valid_code').val()
},
success:function (data) {
if(data.state){
location.href = '/index/'
}else{
$('.error').text(data.msg) }
} })
}); //验证码点击刷新
$('#valid_img').click(function () {
$(this)[0].src += '?'
}) </script>
</body>
</html>

login.html

注:

 css js 静态文件
css js 存在静态文件中 修改之后,client(浏览器)如果没有修改;
需设置一些 浏览器得setting Disable cache

三、form表单、ajax文件上传

django-ajax   http://www.cnblogs.com/yuanchenqi/articles/7638956.html

基于form表单提交数据:
默认值:Content—Type = urlencoded
<form action="" method="post" enctype="application/x-www-form-urlencoded">
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['azZWQlmRhdPPXxtRf9e04B31VZLyVJN8Dc1eAuWEMIxnWShqNP5IyxbozXVRjx8A'],
'user': ['alex'],
'avatar': ['girl.jpg']}> # 其实文件并没有传上来,只是个名称!
print(request.FILES)
<MultiValueDict: {}> 涉及到上传文件时:Content—Type = form-data
<form action="" method="post" enctype="multipart/form-data">
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['gsAIE42u5Io47YttQO9ExBEFuZiVZ965J5C0odChAd6C6jh2ou0m1xM28XsenXrx'],
'user': ['alex']}>
print(request.FILES)
<MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}> 基于Ajax提交数据:
$('#btn').click(function () {
$.ajax({
url:'',
type:'get',
data:{name:'alex',pwd:'123'},
success:function (data) {
console.log(data)
} })
}) 涉及到上传文件时:
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$('#btn').click(function () {
formdate = new FormData(); // 加var 局部, 不加var就是 全局.
formdate.append("user",$('#user').val());
formdate.append("avatar",$('#avatar')[0].files[0]);
formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({
url:'',
type:'post',
data:formdate,
contentType:false,
processData:false,
success:function (data) {
console.log(data)
} })
}) </script> <QueryDict: {'user': ['alice'], 'csrfmiddlewaretoken': ['9ipnZT2GROgz1BFiCZzsYTE32MCBPXKWCVrFJ2CtmjY70WtRaFqasPMqGKMUdL5o']}>
<MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}>
def upload(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
obj = request.FILES.get('avatar') with open(obj.name,'wb') as f:
for line in obj:
f.write(line)
return HttpResponse('OK') return render(request,'upload.html')

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h3>基于form表单提交数据</h3>
{#<form action="" method="post" enctype="application/x-www-form-urlencoded">#}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>用户名 <input type="text" name="user"></p>
<p>头像 <input type="file" name="avatar"></p>
<input type="submit"> </form> <hr>
<h3>基于Ajax提交文件数据</h3>
<form>
{% csrf_token %}
<p>用户名 <input type="text" id="user"></p>
<p>头像 <input type="file" id="avatar"></p>
<input type="button" value="submit" id="btn">
</form> <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$('#btn').click(function () {
formdate = new FormData(); // 加var 局部, 不加var就是 全局.
formdate.append("user",$('#user').val());
formdate.append("avatar",$('#avatar')[0].files[0]);
formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({
url:'',
type:'post',
data:formdate,
contentType:false,
processData:false,
success:function (data) {
console.log(data)
} })
}) </script>
</body>
</html>

四、form表单得注册页面

          

头像默认图片

#avatar{ display: none}
.avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;}
<div class="form-group">
<label for="avatar">头像
<img class="avatar" src="/static/img/default.png" alt="">
</label> <input type="file" id="avatar">
</div>

图像预览

//图像预览
$('#avatar').change(function () {
var choose_file = $(this)[0].files[0]; //文件对象 var reader = new FileReader(); // 阅读器对象
reader.readAsDataURL(choose_file); reader.onload = function (ev) {
$('.avatar').attr('src',reader.result)
}; {#$('.avatar').attr('src',reader.result) // 还没读完,就执行了这句了 出问题了!!#}
//解决办法 reader.onload });

 注意:

为什么   src="/static/img/default.png"    可访问到 ?

因为:  settings   配置了   STATIC_URL = '/static/'

STATIC_URL = '/static/' 
/static/... 对外得文件可以直接访问

Ajax 注册:

from django import forms
from django.forms import widgets,ValidationError from app01.models import UserInfo class RegForm(forms.Form):
user = forms.CharField(max_length=8,label='用户名',
widget=widgets.TextInput(attrs={'class':'form-control'}))
pwd = forms.CharField(min_length=4,label='密码',
widget=widgets.PasswordInput(attrs={'class':'form-control'}))
repeat_pwd = forms.CharField(min_length=4,label='确认密码',
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
email = forms.EmailField(label='邮箱',
widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部钩子
def clean_user(self):
val = self.cleaned_data.get('user') ret = UserInfo.objects.filter(username = val)
if not ret:
return val
else:
raise ValidationError('该用户已存在') # 校验局部钩子得时候 没有办法 拿到 所有得干净数据,
# 如何 校验 两个 字段呢! 全局钩子 # 全局钩子 能得到 任何一个干净得 数据 def clean(self):return self.cleaned_data
def clean(self):
if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
return self.cleaned_data
else:
raise ValidationError('两次密码不一致') from django.http import JsonResponse def reg(request):
if request.method == 'POST':
res = {'user':None,'error_dict':None}
form = RegForm(request.POST) if form.is_valid():
print("clean:",form.cleaned_data) # {"user":'yuan','pwd':"123"}
print(request.FILES) user = form.cleaned_data.get('user')
pwd = form.cleaned_data.get('pwd')
email = form.cleaned_data.get('email')
avatar = request.FILES.get('avatar')
if avatar:
# 接受文件对象 将avatar文件对象下载到avatar字段对应的upload_to指定路径 没指定在 根目录下
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email) res['user'] = user.username else:
print('error:',form.errors) #{"repear_pwd":['',''],"email":['',''],}
res['error_dict'] = form.errors return JsonResponse(res) form = RegForm()
return render(request,'reg.html',locals())
// 注册事件
$('.reg_btn').click(function () {
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("avatar",$('#avatar')[0].files[0]);
formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({
url:'',
type:'post',
contentType:false,
processData:false,
data:formdata,
success:function (data) {
if(data.user){
//注册成功
location.href = "/login/"
}else{
//注册失败
//清空错误信息
$('form span').html("");
$('form .form-group').removeClass('has-error');
// 加载错误信息
$.each(data.error_dict,function (field,error_list) {
// 全局
if(field == "__all__"){
$('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
$('#id_repeat_pwd').parent().addClass('has-error')
}
$('#id_'+field).next().text(error_list[0]).css('color','red');
$('#id_'+field).parent().addClass('has-error')
})
}
} }) })

注意点:

1. 局部钩子 与 全局钩子:

def clean_user(self): pass   局部钩子 只能校验某一个字段
def clean(self): pass        可以校验两个不同得字段,全局钩子,能得到任何一个干净得数据!!
局部钩子得源码:
try:
if isinstance(field, FileField):
initial = self.get_initial_for_field(field, name)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)
全局钩子得源码:
try:
cleaned_data = self.clean()
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data

2. 上传文件:

 formdata = new FormData();
formdata.append("avatar",$('#avatar')[0].files[0]); # 文件对象
formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
 contentType:false,
processData:false,
data:formdata,
。。。

3. ajax得局部刷新:

注册失败:


1. 清空错误信息 
  $('form span').html("");
  $('form .form-group').removeClass('has-error'); 2. 加载错误信息 each
  $.each(data.error_dict,function (field,error_list) {
// 全局 全局得错误信息 field == '__all__'
if(field == "__all__"){
  $('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
$('#id_repeat_pwd').parent().addClass('has-error')
}
$('#id_'+field).next().text(error_list[0]).css('color','red');
$('#id_'+field).parent().addClass('has-error')
})

4.上传文件 得存放地址:media 配置

avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')

 FileField  ImgField  传什么数据呢?  文件对象

 前端:
formdata.append("avatar",$('#avatar')[0].files[0]); # 文件对象 后台:
avatar = request.FILES.get('avatar') # 文件对象
if avatar:
# 接收文件对象 将avatar文件对象下载到avatar字段对应的upload_to(upload_to='avatars/')指定路径下
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email) 真实文件:
upload_to='' 存在项目得根目录下 girl.jpg
upload_to='avatars/' 存在项目得根目录下 /avatars/girl.jpg 注意: 相对路径 不是绝对路径,如果upload_to='/avatars/'会报错!! userinfo:
库里存得是 相对路径!! avatars/girl.jpg
BUT:
用户个人得文件 不应该存在项目得根目录下: ?? 知识点:
静态文件 /static/css..js..img.. 用户可直接 url 访问得到
因为:settings 配置 STATIC_URL = '/static/' 用户文件:存用户得个人信息 头像 简历。。。 存在哪里呢???
media 配置 存用户信息 针对用户上传得文件
avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
        settings
1.MEDIA_ROOT = os.path.join(BASE_DIR,'app01','media') # 针对 upload_to 得相对位置得!! 2.MEDIA_URL = '/media/'                 # 针对 用户通过 url 访问得!! 3.urls.py
from django.views.static import serve
from bbs import settings
re_path(r'media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}) # 针对 用户通过 url 访问得!! media 配置之后
用户可直接访问类似于访问/static/img/...

        upload_to='avatars/' 用户上传得文件就会存在 /media/avatars/girl.jpg  库里存得是,相对路径! avatars/girl.jpg  

  

   注意:
# avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
# 如果用户没有上传图片,使用默认得!!avatar 不需要传!! avatar = request.FILES.get('avatar')
if avatar:
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email)

示例:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>reg</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
<style type="text/css">
.container{ margin-top: 100px;}
#avatar{ display: none}
.avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form action="">
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }} <span class="error pull-right"></span>
</div>
{% endfor %} <div class="form-group">
<label for="avatar">头像
<img class="avatar" src="/static/img/default.png" alt="">
</label> <input type="file" id="avatar">
</div> <input type="button" class="btn btn-default login-btn reg_btn pull-right" value="提交">
</form>
</div>
</div>
</div>
{% csrf_token %} <script src="/static/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
//图像预览
$('#avatar').change(function () {
var choose_file = $(this)[0].files[0]; //文件对象 var reader = new FileReader(); // 阅读器对象
reader.readAsDataURL(choose_file); reader.onload = function (ev) {
$('.avatar').attr('src',reader.result)
}; {#$('.avatar').attr('src',reader.result) // 还没读完,就执行了这句了 出问题了!!#}
//解决办法 reader.onload }); // 注册事件
$('.reg_btn').click(function () {
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("avatar",$('#avatar')[0].files[0]);
formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({
url:'',
type:'post',
contentType:false,
processData:false,
data:formdata,
success:function (data) {
if(data.user){
//注册成功
location.href = "/login/"
}else{
//注册失败
//清空错误信息
$('form span').html("");
$('form .form-group').removeClass('has-error');
// 加载错误信息
$.each(data.error_dict,function (field,error_list) {
// 全局
if(field == "__all__"){
$('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
$('#id_repeat_pwd').parent().addClass('has-error')
}
$('#id_'+field).next().text(error_list[0]).css('color','red');
$('#id_'+field).parent().addClass('has-error')
})
}
} }) }) </script>
</body>
</html>

reg.html

from django import forms
from django.forms import widgets,ValidationError from app01.models import UserInfo class RegForm(forms.Form):
user = forms.CharField(max_length=8,label='用户名',
widget=widgets.TextInput(attrs={'class':'form-control'}))
pwd = forms.CharField(min_length=4,label='密码',
widget=widgets.PasswordInput(attrs={'class':'form-control'}))
repeat_pwd = forms.CharField(min_length=4,label='确认密码',
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
email = forms.EmailField(label='邮箱',
widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部钩子
def clean_user(self):
val = self.cleaned_data.get('user') ret = UserInfo.objects.filter(username = val)
if not ret:
return val
else:
raise ValidationError('该用户已存在') # 校验局部钩子得时候 没有办法 拿到 所有得干净数据,
# 如何 校验 两个 字段呢! 全局钩子 # 全局钩子 能得到 任何一个干净得 数据 def clean(self):return self.cleaned_data
def clean(self):
if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
return self.cleaned_data
else:
raise ValidationError('两次密码不一致') from django.http import JsonResponse def reg(request):
if request.method == 'POST':
res = {'user':None,'error_dict':None}
form = RegForm(request.POST) if form.is_valid():
print("clean:",form.cleaned_data) # {"user":'yuan','pwd':"123"}
print(request.FILES) user = form.cleaned_data.get('user')
pwd = form.cleaned_data.get('pwd')
email = form.cleaned_data.get('email')
avatar = request.FILES.get('avatar')
if avatar:
# 接受文件对象 将avatar文件对象下载到avatar字段对应的upload_to指定路径 没指定在 根目录下
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email) res['user'] = user.username else:
print('error:',form.errors) #{"repear_pwd":['',''],"email":['',''],}
res['error_dict'] = form.errors return JsonResponse(res) form = RegForm()
return render(request,'reg.html',locals())

views.py

知识点1:
jquery对象[0]
jquery对象------------------>DOM
<------------------
$(DOM)
知识点2:
请求形式:
form get
form post
ajax get
ajax post
a标签 get
地址栏 get
注意:
form只有 get post
ajax 有 get post put delete ...
查看 get 修改 post (增 post 删 delete 更新 put) 知识点3: url_encoded
http请求协议:{"user":"alex","pwd":123}-------------->"user=alex&pwd=123"
form-data
{"user":"alex","avatar":obj}-----------> "GET HTTP1.1 /upload/\r\n content—type='url_encoded'\r\n\r\nuser=alex&pwd=123" 请求头:
Content—Type:告诉服务器这次请求数据的格式,默认值:url_encoded
if 上传文件:Content—Type=form-data 知识点4:
form对象渲染样式:
#方式1:
{{form.as_p}}
#方式2:
{{form.user}}
#方式3:
{% for field in form %}
<div>
<label for="">{{ field.label }}</label>
<div>
{{ field }}
</div>
</div>
{% endfor %} 博客系统的登录
---- 基于PIL模块实现的验证码图片
---- 基于session保存验证码
---- 刷新验证码 博客系统的注册
基于ajax和form组件实现注册 ---设计注册页面 self.fields:{"字段":字段规则}
form.is_valid():
self.errors={}
self.clean_data={} UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar) 将avatar文件对象下载到avatar字段对应的upload_to指定路径 (1) media配置:
针对:
avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
avatar = models.ImageField(upload_to='avatars/', default="/avatars/default.png")
MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") (2) MEDIA_URL="/media/"
# media 配置
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),

笔记

BBS - 表、登录、文件上传、注册的更多相关文章

  1. 表单文件上传,ajax文件上传

    原创链接:http://www.cnblogs.com/yanqin/p/5345562.html html代码  index.jsp(表单文件上传) <form action="sh ...

  2. Ajax(form表单文件上传、请求头之contentType、Ajax传递json数据、Ajax文件上传)

    form表单文件上传 上菜 file_put.html <form action="" method="post" enctype="multi ...

  3. 混合表单文件上传到数据库(基于TOMCAT)

    在实际的开发中在实现文件上传的同时肯定还有其他信息需要保存到数据库,就像混合表单在上传完毕之后需要将提交的基本信息插入数据库. 在这个demo中需要用到这个架包来帮助实现 1.定义一个公共类实现文件上 ...

  4. 如何使用PHP上传文件,上传图片,php上传教程,php表单文件上传教程

    使用PHP进行文件上传,主要使用到表单功能和PHP内置的$_FILES函数功能.接下来我们看如何实现PHP上传功能.例子效果图,此例子是在Mac下进行调试成功的. PHP上传图片文件的功能代码如下: ...

  5. 【Demo Project】AjaxSubmit+Servlet表单文件上传和下载

    一.背景 前段时间公司要求我做一个上传和下载固件的页面,以备硬件产品在线升级,现在我把这部分功能抽取出来作为一个Demo Project给大家分享. 话不多说,先看项目演示 --> 演示  源码 ...

  6. form表单文件上传 servlet文件接收

    需要导入jar包 commons-fileupload-1.3.2.jar commons-io-2.5.jar Upload.Jsp代码 <%@ page language="jav ...

  7. 表单文件上传编码方式(enctype 属性)

    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码. 如下: <form action="upload.php" method="post&quo ...

  8. form表单文件上传提交且接口回调显示提交成功

    前端: <form method="post" enctype="multipart/form-data" id="formSubmit&quo ...

  9. flask中的表单文件上传

    在表单中上传文件时,一定要加入 enctype="multipart/form-data" 属性 为什么要加入这个属性呢: enctype就是encodetype就是编码类型的意思 ...

  10. from表单文件上传后页面跳转解决办法

    from表单上传文件,路径跳转后,又不能转发回来. 本人的一个解决办法是.返回一段html代码,浏览器解析后后退一步,回到原来的页面并刷新. return "<html>< ...

随机推荐

  1. 【Java面试题】45 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。

    我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象 ...

  2. YII2中的Html助手和Request组件

    Html助手 1 .在@app\views\test的index.php中: <?php //引入命名空间 use yii\helpers\Html; ?> <?php //[一]表 ...

  3. 使用定时器判断确保某个标签有值才执行方法, 控制js代码执行先后顺序

    使用定时器判断确保某个标签有值才执行方法: var wait = setInterval(function(){ var diqu = $("#diqu").val(); //确保 ...

  4. Oracle行列转换的思考与总结

    最近几天一直在弄Oracle-SQL的问题,涉及到了一些平时没有用到的东西,也因此而在这里郁闷了好久.现在问题得到了解决虽说不算完美.但是还是和大家一起分享一下. 行列转换之一:sum(case wh ...

  5. vs中 main和_tmain的区别

    用过C的人都知道每一个C的程序都会有一个main(),但有时看别人写的程序发现主函数不是int main(),而是int _tmain(),而且头文件也不是<iostream.h>而是&l ...

  6. [extjs] ExtJS 4.2 开发环境搭建

    到官网下载Extjs ,现在最新版的是Ext5.1. 这里用ext4.2演示开发.http://extjs.org.cn/. EXT4.1 在线API 项目结构中ext4.2导入的资源文件: 第一个页 ...

  7. 如何连接 MySQL

    操作如下: [root@localhost ~]$ mysql -uroot -p' # 本地连接 MySQL 服务 [root@localhost ~]$ mysql -uroot -p' -h19 ...

  8. 使用HTML5 的跨域通信机制进行数据同步

    离线应用系统的设计目标就是在网络离线情况下依然可以操作我们的应用系统,并在网络畅通的情况下与服务器进行数据交互. 所以离线应用系统最终会做成类似C/S架构的客户端应用程序.这边基于Chrome或者 S ...

  9. imx6ul开发板

    Feescale飞思卡尔于发布全新的基于ARM Cortex-A7核心的低功耗处理器i.MX6UL,主要面向车载信息处理.家庭能源管理系统.工控领域.物联网网关等应用.具有可扩展性.高性能和低功耗特性 ...

  10. JS对象添加新的字段

    var test={name:"name",age:"12"}; test.id = "12345"; 直接定义添加就成了