Django学习 day73之BBS项目day2

一 服务器保存文件父路径

例如昨天的头像上传,使保存到的文件夹都处在父路径之下

models.py中不需要动

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

settings.py中配置

MEDIA_ROOT=os.path.join(BASE_DIR,'media')
# 由于FileField会自动保存文件,所以默认以MEDIA_ROOT开始往下找,如果没有配,默认以根路径开始
# 以后上传的文件,都是从media路径往下找

二 注册功能错误渲染

注册时提示出错,如两次密码不一致,用户已存在,格式不正确,这些都是用户离开输入框就触发的功能,而不用刷新网页,所以必然是在ajax里实现的功能

接着昨天注册功能里的ajax部分进行补全

$.ajax({
            url: '/register/',
            method: 'post',
            processData: false,
            contentType: false,
            data: formdata,
            success: function (data) {
            	// 没有错误
                if (data.code == 100) {
                    console.log(data.msg)
                    //js控制的跳转
                    location.href = data.url
                } else {
                    //有错误,需要渲染页面
                    $.each(data.error, function (k, v) {
                    	
                    	// 当错误为全局钩子的错误时(也就是两次密码不一致),将错误信息渲染到注册按钮旁的error类(自己去建!别老想着copy)
                        if (k == '__all__') {
                            $(".error").html(v)
                        }
                        // 将错误信息渲染到id_name的下一个标签(错误信息的span标签),同时给其父标签添加类has-error(bootstrap的染红输入框)
                        $("#id_" + k).next().html(v[0]).parent().addClass('has-error')
                    })

                    //过三(3000毫秒)秒钟,错误信息清除,在匿名函数中执行
                    setTimeout(function () {
                    	// 将所有,含有红色文本类的标签清空文本,同时给其父标签删掉染红输入框
                        $('.text-danger').html("").parent().removeClass('has-error')
                    }, 3000)
                }
            }
        })
    })

三 用户名变化校验

视图函数

def check_username(request):
    print('xxx')
    res = {'code': 101, 'msg': '该用户已经存在了小兄弟'}
    username = request.GET.get('username')
    user = models.UserInfo.objects.filter(username=username).count()
    if not user:
        res['code'] = 100
        res['msg'] = '不存在'
    return JsonResponse(res)

js代码

// blur:当光标离开控件上时触发
$('#id_username').blur(function () {
    //this 原生空间,使用它$(),它才变成jq,使用jq的方法
    //alert($(this).val())
    //alert($('#id_username').val())

    $.ajax({
        url: '/check_username/?username=' + $(this).val(),
        method: 'get',
        success: (data) => {
            if (data.code !== 100) {
            	/*这里的success如果没用箭头语法,则会因为作用域的原因,this得到的是None*/
                $(this).next().html(data.msg).parent().addClass('has-error')
            }
        }
        /* 
        success: function (data) {
            if(data.code !==100){
            	这里如果用this就会错误!!作用域问题,success用上es6的箭头语法则可以避免
                $('#id_username').next().html(data.msg).parent().addClass('has-error')
            }
            }
         */
    })
})

四 登陆页面搭建

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <title>登录</title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <h1 class="text-center">登录功能</h1>
        <div class="col-md-6 col-md-offset-3">

            <form id="form">
                {% csrf_token %}

                <div class="form-group">
                    <label for="">用户名</label>
                    <input type="text" name="username" class="form-control">
                </div>
                <div class="form-group">
                    <label for="">密码</label>
                    <input type="password" name="password" class="form-control">
                </div>
                <div class="form-group">
                    <label for="">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" name="valid_code" class="form-control">
                        </div>
                        <div class="col-md-6">
                            <img src="/static/img/default.png" height="30" width="450">
                        </div>
                    </div>
                    
                </div>

                <div class="text-center">
                    <input type="button" value="登录" id="id_submit" class="btn btn-danger"><span
                        class="error text-danger" style="margin-left: 10px"></span>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

五 图片验证码

自定义图片验证码

随机生成rgb数字的函数

# 数字越大颜色越浅
def get_rgb():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

生成函数

需要先导入pillow模块:from PIL import Image, ImageDraw, ImageFont
还有将二进制存入内存的模块:from io import BytesIO

def get_valid(request):
    # 方式一,直接返回一张图片
    # with open('./lhf.jpg','rb') as f:
    #     data=f.read()
    # return HttpResponse(data)

    # 方式二:自己生成一张图片,返回
    # pillow模块:图片处理模块,pip3 install pillow
	# 需要先导入pillow模块:from PIL import Image, ImageDraw, ImageFont 
    # 生成一张图片(Image模块下的new函数,返回一个Image对象)
    # img = Image.new('RGB', (450, 30), (123, 123, 255))
    # # 图片保存(写到硬盘)
    # with open('a.png', 'wb') as f:
    #     img.save(f)
    # # 打开图片
    # with open('./a.png', 'rb') as f:
    #     data = f.read()
    # return HttpResponse(data)

    ## 方式三:把生成的图片写到内存中
    # 需要先引入:from io import BytesIO
    # img = Image.new('RGB', (450, 30), (123, 123, 255))
    # # 图片保存(写到内存中)
    # f=BytesIO()
    # img.save(f,'png')  # 指定图片格式
    # # 打开图片
    # data=f.getvalue()  # 把内容全取出来
    # return HttpResponse(data)

    ## 方法四:在图片上写文字
    # img = Image.new('RGB', (450, 30), (123, 123, 255))
    #
    # # 把图片放到画板上
    # img_draw=ImageDraw.Draw(img)
    # # 在x轴0,y轴0的位置写文字
    # img_draw.text((0,0),'python')
    #
    # f=BytesIO()
    # img.save(f,'png')
    # data=f.getvalue()
    # return HttpResponse(data)

    ## 方式五:图片上写文字,字体是指定的字体,字的颜色随机
    # img = Image.new('RGB', (450, 30), (123, 123, 255))
    #
    # img_draw = ImageDraw.Draw(img)
    # img_font = ImageFont.truetype('./static/font/xgdl.ttf', 23)  # 字体文件,字号大小23
    # img_draw.text((0, 0), 'python', (255, 0, 255), img_font)  # 位置,内容,字体颜色,字体
    #
    # f = BytesIO()
    # img.save(f, 'png')
    # data = f.getvalue()
    # return HttpResponse(data)

    ## 方式6 最终方案
    # img = Image.new('RGB', (450, 30), get_rgb())  # get_rgb():使用随机生成rgb数字的函数
    img = Image.new('RGB', (450, 30), (255,255,255))

    img_draw = ImageDraw.Draw(img)
    img_font = ImageFont.truetype('./static/font/ss.TTF', 25)
    # 随机生成5个大写字母,小写字母,数字
    valid_code=''
    for i in range(5):
        low_char = chr(random.randint(97, 122))
        num_char = random.randint(0, 9)
        upper_char = chr(random.randint(65, 90))
        res = random.choice([low_char, num_char, upper_char])
        valid_code+=str(res)
        img_draw.text((i*63+50, 0), str(res), get_rgb(), img_font)
    print(valid_code)  # 打印验证码
    # 把验证码存到session中,使每个用户都有其独特的验证码
    request.session['valid_code']=valid_code
    # 画线和点圈,这个请直接copy
    width = 450
    height = 30
    for i in range(10):  # 画十根线
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        # 在图片上画线
        img_draw.line((x1, y1, x2, y2), fill=get_rgb())

    for i in range(50):  # 画50个点跟弧形
        # 画点
        img_draw.point([random.randint(0, width), random.randint(0, height)], fill=get_rgb())
        x = random.randint(0, width)
        y = random.randint(0, height)
        # 画弧形
        img_draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_rgb())

    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()
    return HttpResponse(data)  # 因为要随时刷新换图片,所以是传给ajax的数据,用HttpResponse

借助第三方模块实现验证码

点击这里跳转

六 点击图片验证码更新

$("#id_valid_code").click(function () {
        var url = $("#id_valid_code")[0].src
        $("#id_valid_code")[0].src = url + '?'  // src变换时就会发送一次请求,这里的方法是添加无意义的问号
    })

七 登陆功能

后台

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        res = {'code': 100, 'msg': None}
        username = request.POST.get('username')
        password = request.POST.get('password')
        valid_code = request.POST.get('valid_code')
        # 校验验证码是否正确,忽略大小写
        if request.session.get('valid_code').upper() == valid_code.upper():
            # 不使用这个
            # models.UserInfo.objects.filter(username=username,password=password)
            user = auth.authenticate(username=username, password=password)
            if user:
                # 调用一些login
                auth.login(request, user)
                res['msg'] = '登录成功'
                res['url'] = '/index/'
            else:
                res['code'] = 101
                res['msg'] = '用户名或密码错误'
        else:
            res['code'] = 102
            res['msg'] = '验证码错误'
        return JsonResponse(res)

前台

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <title>登录</title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <h1 class="text-center">登录功能</h1>
        <div class="col-md-6 col-md-offset-3">

            <form id="form">
                {% csrf_token %}

                <div class="form-group">
                    <label for="">用户名</label>
                    <input type="text" name="username" class="form-control">
                </div>
                <div class="form-group">
                    <label for="">密码</label>
                    <input type="password" name="password" class="form-control">
                </div>
                <div class="form-group">
                    <label for="">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" name="valid_code" class="form-control">
                        </div>
                        <div class="col-md-6">
                            <img src="/get_valid/" height="30" width="450" id="id_valid_code">
                        </div>
                    </div>

                </div>

                <div class="text-center">
                    <input type="button" value="登录" id="id_submit" class="btn btn-danger"><span
                        class="error text-danger" style="margin-left: 10px"></span>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
<script>
    $("#id_valid_code").click(function () {
        var url = $("#id_valid_code")[0].src
        $("#id_valid_code")[0].src = url + '?'
    })

    $("#id_submit").click(function () {
        //不建议在js中写模板语法
        $.ajax({
            url: '/login/',
            method: 'post',
            data: {
                'username': $('[name="username"]').val(),
                'password': $('[name="password"]').val(),
                'valid_code': $('[name="valid_code"]').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
            },
            success:function (data) {
                if(data.code==100){
                    location.href=data.url
                }else {
                    $('.error').html(data.msg)
                }
            }
        })
    })
</script>
</html>

八 博客首页导航条

后台

def index(request):
    return render(request, 'index.html')


def logout(request):
    auth.logout(request)
    return redirect('/')

前台

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <script src="/static/bootstrap/js/bootstrap.min.js"></script>
    <title>博客园首页</title>
</head>
<body>


<div class="head">
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">博客园</a>
            </div>

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="/index/">首页 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">新闻</a></li>

                </ul>
                {% if request.user.is_authenticated %}
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">{{ request.user.username }}</a></li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                               aria-haspopup="true" aria-expanded="false">更多 <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="#">修改密码</a></li>
                                <li><a href="#">修改头像</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="/logout/">退出登录</a></li>
                            </ul>
                        </li>
                    </ul>
                {% else %}
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="/login/">登录</a></li>
                         <li><a href="/register/">注册</a></li>
                    </ul>
                {% endif %}

            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
</div>
<div class="container-fluid">
    <div class="body">
        <div class="row">
            <div class="left_content col-md-2"></div>
            <div class="middle_content col-md-7"></div>
            <div class="right_content col-md-3"></div>
        </div>
    </div>
</div>

</body>
</html>

补充异步知识

  1. 程序:躺在硬盘上就是一堆文件,加载到内存,就是一堆指令,被cpu调度执行

  2. 进程,线程,协程

  3. 进程是资源分配的最小单位 跨进程通信 IPC ,通过共享变量实现不了,借助Queue,借助文件,借助数据库,借助redis,借助消息队列(专业干这个事)

  4. 线程是cpu调度的最小单位(程序执行的最小单位),线程通信:共享变量(并发安全问题,锁,分布式锁,悲观锁,乐观锁)

  5. 协程:当线程下实现并发(保存状态+切换)

  6. 一旦使用了异步,后续全用异步

  7. await 和 async 关键字
    async:声明协程函数
    await:io操作前面加

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值