實戰之BBS(仿博客園寫一個論壇)(二)登陸頁面,網站首頁的實現

一.登陸頁面

1.效果展現:css

2.技術點:html

2.1驗證碼:驗證碼這個功能用了Image,ImageDraw,ImageFont,random,BytesIO模塊和session前端

Image是新建立一個圖片,ImageDraw至關於在這個圖片上建立一個畫筆,ImageFont指定字體的格式jquery

random隨機模塊,BytesIO開闢一片字節類型的內存空間,session用於存儲驗證碼,驗證碼的具體細節請看上篇博客ajax

2.2登陸驗證:咱們的註冊的時候,用的是auth.create_user()方法,這種方法會讓咱們的密碼被加密,在數據庫中以下圖所示:數據庫

因此說咱們只能把從前端的獲取的密碼,通過一樣的加密以後再和數據庫中的數據進行比對django

  user=auth.authenticate(request,username=username,password=password)

若是user存在,登陸成功,保持登陸狀態,不然返回錯誤信息,並對前端進行渲染bootstrap

2.2.1登陸成功:後端

首先用auth.login把user綁定,至關於session和cookie可是使用方法比這兩個都簡單,執行以後,不退出登陸的狀況下,request.user就是auth.login(request,user)裏面的usercookie

auth.login(request,user)

登陸成功以後,給前端返回數據,首先在函數開頭定義一個response_msg用於標識成功或失敗,初始化:

 respone_msg={'code':100,'msg':''}

當登陸成功的時候,code不變,給response添加一個URL:

  respone_msg['url']='/home'

當登陸成功的時候,跳轉到home頁面。固然了這行代碼也須要前端的配合,前端:

success:function (data) {
                if(data.code==100){
                    location.href=data.url
                }

2.2.2登陸失敗:

登陸失敗,response_msg['code']變爲101(或者隨意一個數,和成功區別開就好),msg變爲失敗的信息,好比是驗證碼出錯仍是帳號密碼錯誤

把返回的msg數據在前端進行渲染,顯示出來,效果以下:

3.流程圖:

 

 4.具體代碼:

後端代碼:

from django.shortcuts import render,HttpResponse,redirect
from app01 import myforms
from app01 import models
from django.http import JsonResponse
# Create your views here.
from PIL import Image,ImageDraw,ImageFont
from io import BytesIO,StringIO
from django.contrib import auth
import random
#隨機數據
def r_num(number):
    if number==2:
        return random.randint(0,128),random.randint(0,128),random.randint(0,128)
    if number == 1:
        return random.randint(128, 255), random.randint(128, 255), random.randint(128, 255)
#驗證碼函數
def yzm(request):
    yzm_img=Image.new("RGB",(260,40),r_num(1))
    draw=ImageDraw.Draw(yzm_img)
    font=ImageFont.truetype('static/1.ttf',40)
    code=''
    for i in range(5):
        random_num=str(random.randint(0,9))
        random_up=str(chr(random.randint(65,90)))
        random_low=str(chr(random.randint(97,122)))
        random_code=random.choice([random_num,random_up,random_low])
        draw.text((20+40*i,-5),random_code,r_num(2),font)
        code+=random_code
    io_obj=BytesIO()
    yzm_img.save(io_obj,'png')
    request.session['code']=code
    return HttpResponse(io_obj.getvalue())
#登陸函數
def login(request):
    respone_msg={'code':100,'msg':''}
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POST.get('password')
        yzm=request.POST.get('yzm')

        if request.session.get('code').upper()==yzm.upper():
            user=auth.authenticate(request,username=username,password=password)
            if user:
                auth.login(request,user)
                respone_msg['url']='/home'
            else:
                respone_msg['code']=101
                respone_msg['msg']='用戶名或密碼錯誤'
        else:
            respone_msg['code']=102
            respone_msg['msg']='驗證碼錯誤'
        return  JsonResponse(respone_msg)
    return render(request,'login.html',locals())
後端代碼

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <h1 class="text-center">登陸頁面</h1>
    <div class="row">
        <form class="col-lg-offset-3 col-lg-6">
            {% csrf_token %}
            <div class="form-group">
                <label for="id_username">用戶名</label>
                <input type="text" class="form-control" id="id_username" placeholder="用戶名">
            </div>
            <div class="form-group">
                <label for="id_password">密碼</label>
                <input type="password" class="form-control" id="id_password" placeholder="密碼">
            </div>
            <div class="form-group">
                <label for="id_yzm">驗證碼</label>
                <input type="text" class="form-control" id="id_yzm" placeholder="驗證碼">
                <div style="margin-top: 30px"><img src="/yzm/" alt="" id="img_yzm"></div>
            </div>
            <div><input type="button" id="button_id" value="登陸" class="btn btn-primary"></div>
            <div> <span id="error" style="color: red"></span></div>
        </form>
    </div>
</div>
<script>
    $('#img_yzm').click(function () {
         var path2 = $(this).attr('src');
        $(this).attr('src',path2+='?')
    });
    $('#button_id').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{
                'username':$('#id_username').val(),
                'password':$('#id_password').val(),
                'yzm':$('#id_yzm').val(),
                'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()
            },
            success:function (data) {
                if(data.code==100){
                    location.href=data.url
                }
                else {
                    $('#error').html(data.msg)
                }
            }
        })
    })
</script>
</body>
</html>

前端代碼
前端

 

 

二.首頁的實現

1.效果展現:

,上圖能夠分爲左右兩邊面板模塊,中間文章展現模塊,頁面頂部導航欄模塊,頂部導航欄模塊分爲登陸狀態和非登陸狀態

非登陸狀態:

登陸狀態:

2.實現步驟

2.1左右兩邊面板模塊:

左右兩邊面板模塊用bootstarp的柵格系統完成,左2,中8,右2,而後再去copy3個面板,完成

2.2中間數據的展現:

後端操做很簡單,只須要獲取文章表的全部數據發送給前端便可

 article_list=models.Article.objects.all()
    return render(request,'home.html',locals())

前端代碼,把後端發過來的數據,用for循環渲染

{% for article in article_list %}
            <div class="media">
                <div class="media-left">
                    <a href="#">
                        <img class="media-object" data-src="holder.js/64x64" alt="64x64"
                             src="/media/{{ article.blog.userinfo.avatar }}"
                             data-holder-rendered="true" style="width: 64px; height: 64px;">
                    </a>
                </div>
                <div class="media-body">
                    <h4 class="media-heading"><a href="/{{ article.blog.userinfo.username }}/{{ article.id }}">{{ article.title }}</a></h4>
                    {{ article.desc }}
                    <div>
                        <span>發佈時間:{{ article.create_time }} 點贊數:{{ article.up_num }} 評論數:{{ article.comment_num}}</span>
                    </div>
                </div>
            </div>
            {% endfor %}

2.3頁面頂部導航欄

首先實現不一樣狀態下的前端切換,後端是locals()傳值,全部request也被傳到了前端,那麼就能夠經過request.user判斷用戶是否登陸

{% if request.user.is_authenticated %}
<li><a href="/{{ request.user.username }}/GL">{{ 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="/set_password">修改密碼</a></li>
<li><a href="/set_avatar">修改頭像</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">註銷</a></li>
{% else %}
<li><a href="/login">登陸</a></li>
<li><a href="/register">註冊</a></li>
</ul>
</li>{% endif %}

2.3.1非登陸狀態下

非登陸狀態下,給兩個a標籤添加路徑,

 <li><a href="/login">登陸</a></li>
            <li><a href="/register">註冊</a></li>

2.3.2 登陸狀態下,有三個功能,修改密碼,修改頭像,註銷

修改密碼:首先在url文件中添加路徑,在views中添加函數,爲a標籤加上路徑,在templates建立一個修改密碼頁面

效果如上

修改密碼要有原密碼。原密碼的是加密的,因此又須要一個函數request.user.check_password()

驗證以後,進行兩次新密碼的比對,沒有問題的話,進行保存,又又又要對密碼進行加密,因此須要另一個函數request.user.set_password(new_password),還有設置完以後別忘記保存request.user.save()

後端:

def set_password(request):
    respone_msg={'code':100,'msg':''}
    if request.method=="POST":
        password=request.POST.get('password')
        if request.user.check_password(password):
            new_password=request.POST.get('new_password')
            re_new_password=request.POST.get('re_new_password')
            if new_password==re_new_password:
                respone_msg['url']='/login'
                request.user.set_password(new_password)
                request.user.save()
                auth.logout(request)
            else:
                respone_msg['code']=101
                respone_msg['msg']='兩次密碼不一致'
        else:
            respone_msg['code'] = 102
            respone_msg['msg'] = '原密碼不正確'
        return JsonResponse(respone_msg)

    return render(request,'set_password.html',locals())
修改密碼後端源碼

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<body>
<div class="container">
    <h1 class="text-center">修改密碼</h1>
    <div class="row">
        <form class="col-lg-offset-3 col-lg-6">
            {% csrf_token %}
            <div class="form-group">
                <label for="id_username">用戶名</label>
                <input type="text" class="form-control" id="id_username" placeholder="用戶名" value={{ request.user.username }} disabled>
            </div>
            <div class="form-group">
                <label for="id_password">密碼</label>
                <input type="password" class="form-control" id="id_password" placeholder="密碼">
            </div>
             <div class="form-group">
                <label for="id_password2">新密碼</label>
                <input type="password" class="form-control" id="id_password2" placeholder="密碼">
            </div>
             <div class="form-group">
                <label for="id_password3">重複新密碼</label>
                <input type="password" class="form-control" id="id_password3" placeholder="密碼">
            </div>

            <div><input type="button" id="button_id" value="修改" class="btn btn-primary"></div>
            <div> <span id="error" style="color: red"></span></div>
        </form>
    </div>
</div>
<script>
    $('#button_id').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{
                'password':$('#id_password').val(),
                'new_password':$('#id_password2').val(),
                're_new_password':$('#id_password3').val(),
                'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()
            },
            success:function (data) {
                if(data.code==100){
                    location.href=data.url
                }
                else {
                    $('#error').html(data.msg)
                }
            }
        })
    })
</script>
</body>
</body>
</html>
前端源碼

 

修改頭像:


頭像修改的原理和註冊時是同樣的,簡單很少BB

def set_avatar(request):
    blog = request.user.blog
    username = request.user.username
    if request.method=="POST":
        file = request.FILES.get('myfile')
        user_obj = models.UserInfo.objects.get(blog=blog)
        user_obj.avatar = file
        user_obj.save()
        return JsonResponse({'url':'/home','code':'100'})
    return render(request,'set_avatar.html',locals())
後端代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-lg-6">
            {% csrf_token %}
            <label for="file_id"> 頭像
                <img data-src="holder.js/140x140" class="img-rounded" alt="140x140" style="width: 140px; height: 140px;"
                     src="/media/{{ request.user.avatar }}" data-holder-rendered="true" id="img_id">
            </label>
            <input type="file" id="file_id" class="hidden">
            <p><input type="button" id="button_id" value="修改"></p>

        </div>

    </div>
</div>
<script>
    $('#file_id').change(function () {
        var file = $(this)[0].files[0];
        var read = new FileReader();
        read.readAsDataURL(file);
        read.onload = function () {
            $('#img_id').attr('src', read.result)
        }
    });
    $('#button_id').click(function () {
    var formdata=new FormData();
     formdata.append('myfile',$('#file_id')[0].files[0]);
     formdata.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val());
    $.ajax({
        url:"",
        type:'post',
        data:formdata,
        processData: false,
        contentType: false,
        success:function (data) {
          if(data.code==100){
            location.href=data.url
          }
        }
    })
})
</script>
</body>
</html>
前端

 

至於最後一個註銷就簡單了:

和auth.login相對應的函數,auth.logout

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

首頁完整代碼:
後端:
#首頁
def home(request):
    article_list=models.Article.objects.all()
    return render(request,'home.html',locals())
#註銷
def logout(request):
    auth.logout(request)
    return redirect('/home')
#修改密碼
def set_password(request):
    respone_msg={'code':100,'msg':''}
    if request.method=="POST":
        password=request.POST.get('password')
        if request.user.check_password(password):
            new_password=request.POST.get('new_password')
            re_new_password=request.POST.get('re_new_password')
            if new_password==re_new_password:
                respone_msg['url']='/login'
                request.user.set_password(new_password)
                request.user.save()
                auth.logout(request)
            else:
                respone_msg['code']=101
                respone_msg['msg']='兩次密碼不一致'
        else:
            respone_msg['code'] = 102
            respone_msg['msg'] = '原密碼不正確'
        return JsonResponse(respone_msg)

    return render(request,'set_password.html',locals())
#修改頭像
def set_avatar(request):
    blog = request.user.blog
    username = request.user.username
    if request.method=="POST":
        file = request.FILES.get('myfile')
        user_obj = models.UserInfo.objects.get(blog=blog)
        user_obj.avatar = file
        user_obj.save()
        return JsonResponse({'url':'/home','code':'100'})
    return render(request,'set_avatar.html',locals())
首頁後端代碼

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">博客園</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
            </ul>
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li><a href="/{{ request.user.username }}/GL">{{ 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="/set_password">修改密碼</a></li>
                            <li><a href="/set_avatar">修改頭像</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/logout">註銷</a></li>
                            {% else %}
                            <li><a href="/login">登陸</a></li>
                            <li><a href="/register">註冊</a></li>
                        </ul>
                    </li>{% endif %}
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
            <div class="panel panel-danger">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
        </div>
        <div class="col-md-8">
            {% for article in article_list %}
            <div class="media">
                <div class="media-left">
                    <a href="#">
                        <img class="media-object" data-src="holder.js/64x64" alt="64x64"
                             src="/media/{{ article.blog.userinfo.avatar }}"
                             data-holder-rendered="true" style="width: 64px; height: 64px;">
                    </a>
                </div>
                <div class="media-body">
                    <h4 class="media-heading"><a href="/{{ article.blog.userinfo.username }}/{{ article.id }}">{{ article.title }}</a></h4>
                    {{ article.desc }}
                    <div>
                        <span>發佈時間:{{ article.create_time }} 點贊數:{{ article.up_num }} 評論數:{{ article.comment_num}}</span>
                    </div>
                </div>
            </div>
            {% endfor %}
        </div>
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
            <div class="panel panel-danger">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">
                    <h3 class="panel-title">廣告位</h3>
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
                <div class="panel-body">
                    廣告位招租
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>
首頁前端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-lg-6">
            {% csrf_token %}
            <label for="file_id"> 頭像
                <img data-src="holder.js/140x140" class="img-rounded" alt="140x140" style="width: 140px; height: 140px;"
                     src="/media/{{ request.user.avatar }}" data-holder-rendered="true" id="img_id">
            </label>
            <input type="file" id="file_id" class="hidden">
            <p><input type="button" id="button_id" value="修改"></p>

        </div>

    </div>
</div>
<script>
    $('#file_id').change(function () {
        var file = $(this)[0].files[0];
        var read = new FileReader();
        read.readAsDataURL(file);
        read.onload = function () {
            $('#img_id').attr('src', read.result)
        }
    });
    $('#button_id').click(function () {
    var formdata=new FormData();
     formdata.append('myfile',$('#file_id')[0].files[0]);
     formdata.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val());
    $.ajax({
        url:"",
        type:'post',
        data:formdata,
        processData: false,
        contentType: false,
        success:function (data) {
          if(data.code==100){
            location.href=data.url
          }
        }
    })
})
</script>
</body>
</html>
修改頭像前端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<body>
<div class="container">
    <h1 class="text-center">修改密碼</h1>
    <div class="row">
        <form class="col-lg-offset-3 col-lg-6">
            {% csrf_token %}
            <div class="form-group">
                <label for="id_username">用戶名</label>
                <input type="text" class="form-control" id="id_username" placeholder="用戶名" value={{ request.user.username }} disabled>
            </div>
            <div class="form-group">
                <label for="id_password">密碼</label>
                <input type="password" class="form-control" id="id_password" placeholder="密碼">
            </div>
             <div class="form-group">
                <label for="id_password2">新密碼</label>
                <input type="password" class="form-control" id="id_password2" placeholder="密碼">
            </div>
             <div class="form-group">
                <label for="id_password3">重複新密碼</label>
                <input type="password" class="form-control" id="id_password3" placeholder="密碼">
            </div>

            <div><input type="button" id="button_id" value="修改" class="btn btn-primary"></div>
            <div> <span id="error" style="color: red"></span></div>
        </form>
    </div>
</div>
<script>
    $('#button_id').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{
                'password':$('#id_password').val(),
                'new_password':$('#id_password2').val(),
                're_new_password':$('#id_password3').val(),
                'csrfmiddlewaretoken':$("[name='csrfmiddlewaretoken']").val()
            },
            success:function (data) {
                if(data.code==100){
                    location.href=data.url
                }
                else {
                    $('#error').html(data.msg)
                }
            }
        })
    })
</script>
</body>
</body>
</html>
修改密碼前端
相關文章
相關標籤/搜索