bbs技术总结

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.pngmedia里面就会多出一个存放头像的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">

这样就可以看到别人的头像

上一篇:BBs项目评论端口


下一篇:bbs项目表设计