bbs技术点总结
js只要用到内置对象,直接用new生成就可以了
用户注册上传头像
<div class="form-group">
<label for="myfile">头像
{% load static %}
<img id="myimg" src="{% static 'img/default.png' %}" alt="" width="80" style="margin-left: 20px"></label>
<input type="file" id="myfile" name="avater" style="display: none">
</div>
<script>
//文本域变化事件
$('#myfile').change(function () {
//文件阅读器对象
//1.先生成一个文件阅读器对象
let myFileReadObj = new FileReader(); // 文件阅读器
//2. 获取用户上传的头像文件
let fileObj = $(this)[0].files[0]; //获取文件
// 3.将文件对象交给文件阅读器读取
myFileReadObj.readAsDataURL(fileObj) //异步操作,io操作,这行代码文件还没有读完,就已经开始执行下一句代码,在前端不显示
//4.利用文件阅读器将文件展示到页面去 修改src属性
//等待文件阅读器加载完之后,在执行
myFileReadObj.onload = function(){ $('#myimg').attr('src',myFileReadObj.result)}
})
- 这里我们要用到文本与变化事件,利用文件阅读器对象,我们要先生成一个文件阅读器对象,
- 获取用户上传的头像文件读取出来
- 将文件对象交给文件阅读器读取出来文件
- 利用文件阅读器将文件展示到页面上去,就要修改src属性,
myFileReadObj.readAsDataURL(fileObj)
和$('#myimg').attr('src',myFileReadObj.result)
这两部是一个异步操作,如果你在执上一代码的同时文件还没有读取出来,同时他还在执行下一句代码,这样会造成你上传之后在前端是不显示你上传的头像,空白区,我们要等文件加载完毕在执行下一局,myFileReadObj.onload
$('#id_commit').click(function () {
// 发送ajax请求 我们发送的数据中即包含普通的键值也包含文件
let formDataObj = new FormData();
// 1.添加普通的键值对
{#console.log($('#myform').serializeArray()) // [{},{},{},{},{}] 只包含普通键值对#}
$.each($('#myform').serializeArray(),function (index,obj) {
{#console.log(index,obj)#} // obj = {}
formDataObj.append(obj.name,obj.value)
});
// 2.添加文件数据
formDataObj.append('avatar',$('#myfile')[0].files[0]);
// 3.发送ajax请求
$.ajax({
url:"",
type:'post',
data:formDataObj,
// 需要指定两个关键性的参数
contentType:false,
processData:false,
success:function (args) {
if (args.code==1000){
// 跳转到登陆页面
window.location.href = args.url
}els
// 如何将对应的错误提示展示到对应的input框下面
// forms组件渲染的标签的id值都是 id_字段名
$.each(args.msg,function (index,obj) {
{#console.log(index,obj) // username ["用户名不能为空"]#}
let targetId = '#id_' + index;
$(targetId).next().text(obj[0]).parent().addClass('has-error')
})
}
}
})
})
def register(request):
# 产生一个空对象
register_form = myforms.MyRegForm()
if request.method == 'POST':
back_dic = {'code':'', 'msg': ''}
# 校验数据是否合法
register_form = myforms.MyRegForm(request.POST)
# 判断数据是否合法
if register_form.is_valid():
clean_data = register_form.cleaned_data # 将校验通过的数据字典赋值给一个变量
# 将字典里面吗的confirm_password键值对删除
clean_data.pop('confirm_password')
# 用户头像
file_obj = request.FILES.get('avatar')
"""
针对用户头像一定要判断是否传之,不能直接添加到字典里面去
"""
if file_obj:
clean_data['avatar'] = file_obj
# 直接操作数据库保存到字典里面
models.UserInfo.objects.create_user(**clean_data) # 将键值对**打散传到数据库
# 判断正确跳转到登录页面
back_dic['url'] = '/login/'
else:
back_dic['code'] = 2000
back_dic['msg'] = register_form.errors
return JsonResponse(back_dic)
return render(request, 'register.html', locals())
前端:
-
头像的功能完成之后,剩下的就是将利用ajax将文件发送到后端,前端要先利用内置对象获取数据,添加不同键值对,我们可以利用
serializeArray()
拿到他所有的键值对,利用each循环拿到每一个对象的键值对 -
利用append添加文件数据,发送ajax请求,这里面我们要指定两个关键参数
contentType: false
,processData: false
, -
如果后端保存数据成功,就跳转到后端写好传过来的指定页面,如果校验数据失败就在input框下面展现出对应的错误
-
当我们看见错误的信息之后,如果把鼠标放上去,指定的错误就会消失,给所有的input框绑定获取焦点事件,将input下面的span标签和input外面的div标签修改内容和属性
后端
- 校验数据输入的是否合法,将合法的数据赋值给一个变量,赋值给一个变量方便我们删除确认密码的键值对,因为我们在写models的时候没有这个字段,针对用户头像一定要判断是否传之,不能直接添加到字典里面去,在models里面我们给他默认了一个头像
- 操作数据库保存数据,定义字典将信息返回给ajax,ajax都到在页面展示对应的页面信息
生成登录验证码
如何生成一个验证码,然后点击它就可以刷新呢。
利用pip3 install pillow ,这个是图片相关的模块。
导入模块:from PIL import Image, ImageDraw, ImageFont
- Image 生成图片
- ImageDraw 能够在图片上添加东西
- ImageFont 控制字体的样式
推导1:
直接获取后端生成的图片二进制数据发送给前端
with open(r'static/img/111.jpg','rb') as f:
data = f.read()
return HttpResponse(data)
推导2
利用pillow模块动态产生图片
img_obj = Image.new('RGB',(430,35),'green')
img_obj = Image.new('RGB',(430,35),get_random())
# 将图片对象 保存起来
with open('xxx.png','wb') as f:
img_obj.save(f,'png')
# 再将文件对象读取出来
with open('xxx.png','rb') as f:
data = f.read()
return HttpResponse(data)
推导3
我们可以看到利用文件存储繁琐而且IO操作效率低,我们可以借助内存管理模块
from io import BytesIO,StringIO
img_obj = Image.new('RGB', (430, 35), get_random())
io_obj = BytesIO()
img_obj.save(io_obj,'png') # 生成一个内存管理器对象
return HttpResponse(io_obj.getvalue()) # 从内存管理器中读取二进制的图片数据返回给前端
推导4
写成图片验证码
img_obj = Image.new('RGB', (430, 35), get_random())
img_draw = ImageDraw.Draw(img_obj) # 产生一个画笔对象
img_font = ImageFont.truetype('static/font/222.ttf',30) # 字体样式 大小
最终成型
import random
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
def get_code(request):
img_obj = Image.new('RGB', (430, 35), get_random()) # 注意:这里的430,35要和前端的一致
img_draw = ImageDraw.Draw(img_obj)
img_font = ImageFont.truetype('static/font/222.ttf',30)
code = ''
for i in range(5):
random_upper = chr(random.randint(65,90))
random_lower = chr(random.randint(97,122))
random_int = str(random.randint(0,9))
tmp = random.choice([random_lower,random_upper,random_int])
img_draw.text((i*60+60,-2),tmp,get_random(),img_font)
code += tmp
print(code)
request.session['code'] = code
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
- 实现低级验证码图片刷新验证码,这样设置后每次点击图片相当于超后端发送一次get请求获取一个新的验证码图片
{# 点击验证码图片刷新验证码 #}
$('#code_img').click(function () {
$(this).attr('src', '{% url "get_code" %}?') // src='/get_code/?'url后面加?的操作
});
admin的使用
以前写图书的展示列表,我们给它添加增删改查的功能,特别的麻烦,现在有很多张表的展示,我们不可能慢慢的写这些功能,django给我们提供了admin后台管理,我们可以利用admin实现增删改查,添加数据。
首先要创建超级用户,只有超级用户才能够操作admin的这些功能。
刚开始登录进去的时候只用一张用户表,我们想要添加其他的表,必须添加注册
from django.contrib import admin
from app01 import models
# Register your models here.admin
admin.site.register(models.UserInfo)
admin.site.register(models.Blog)
admin.site.register(models.Article)
admin.site.register(models.Atricle2Tag)
admin.site.register(models.UpAndDown)
admin.site.register(models.Category)
admin.site.register(models.Tag)
admin.site.register(models.Comment)
这样我们就可以使用这些表,但是他们是英文的,我们可以在model.py里面改变他们的名字
class Meta:
verbose_name_plural='用户表'
我们进去操作添加添加一条数据显示的是对象,
class UserInfo(AbstractUser):
...
def __str__(self):
return self.username
避免造成不便语义不明,打印出来
在model里面的字段添加verbose_name='创建时间'
会在admin后天帮助我们把字段的名称改成中文
制作站点
打开博客园,在博客园的url后面输入别人的站点名称就可以进到他们的站点,如https://home.cnblogs.com/the3times在后面输入the3times
就会进到这个人的博客园的主页,这个是url来配置的,利用urlre
匹配规则就可以实现
url(r'^(?P<username>\w+)/$',views.site,name='site'),
media的配置
网站用户使用的静态文件默认放在static里面,用户上传的静态文件应该单独放在一个文件夹下,可以使用media配置,该配置可以让用户上传的所有的文件 固定存放在指定的文件夹下
settings.py
# 配置用户上传的文件
MEDIA_ROOT = os.path.jion(BASE_DIR,'media')
我们配置后,我们上传文件会自动生成media文件,比如我们注册上传的头像会到这个地方,你存的路径在数据库中也不会改变,
假如你在model.py里面存的路径是avatar/111.png
media里面就会多出一个存放头像的avatar/111.png
这个就是你存放的头像路径。
class UserInfo(AbstractUser):
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png', verbose_name='用户头像')
在前端点击这个头像能够查看到这个头像,需要我们在后端开设一个指定的文件夹资源
在url.py配置参数
from django.views.static import serve
from bbs import settings
url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}),
如果你还想暴漏更多资源,在settings修改文件夹名,想暴露源码也可以,问题就大了
最后在html配置,渲染后的路径/media/avatar/default.png/
<img class="media-object" src="/media/{{ article_obj.blog.userinfo.avatar }}" alt="..." width="40">
这样就可以看到别人的头像