1. 程式人生 > 其它 >BBS專案搭建分步過程

BBS專案搭建分步過程

BBS專案搭建分步過程

1. 註冊頁面補充完善

# 註冊前端檔案 register.html檔案中補充:
// 提交ajax
        $.ajax({
            url: '',
            type: 'post',
            data: myFormData,
            contentType: false,
            processData: false,
            success: function (res) {
                console.log(res)
                if (res.status == 200) {
                    layer.msg(res.msg, {icon:1}, function () {
                        location.href = res.url;
                    })
                } else {
                    layer.msg(res.msg,);
                }
            }
        })
    })
</script>
</body>
</html>



# views.py中補充:

from django.http import JsonResponse
from app01 import models

# 1.註冊功能
def register(request):
    # 後端一定要對引數進行驗證
    if request.method == 'POST':
        # 返回的是json格式的資料
        back_dic = {'status': 200, 'msg': '註冊成功', 'data': {}}
        # 1.1. 接收引數
        username = request.POST.get('username')
        password = request.POST.get('password')
        re_password = request.POST.get('re_password')
        email = request.POST.get('email')
        img = request.POST.get('img')

        # 1.2. 驗證引數, 先驗證不正確的引數
        if not username:
            '''
                響應狀態碼
                業務狀態碼
                財務相關的業務,使用者相關的,訂單相關的
                1001         2001      30
            '''
            back_dic['status'] = 1001
            back_dic['msg'] = '使用者名稱必須填寫'
            return JsonResponse(back_dic)

        if password != re_password:
            back_dic['status'] = 1002
            back_dic['msg'] = '兩次密碼不一致'
            return JsonResponse(back_dic)

        # 驗證使用者名稱是否存在
        res = models.UserInfo.objects.filter(username=username).first()
        if res:
            back_dic['status'] = 1003
            back_dic['msg'] = '使用者名稱已經存在'
            return JsonResponse(back_dic)

        # 1.3. 處理正確的業務邏輯
        data_dic = {}
        if img != 'undefined':
            data_dic['avatar'] = img

        # 處理密碼
        import hashlib
        from django.conf import settings
        m = hashlib.md5()
        password = password + settings.SECRET_KEY
        m.update(password.encode('utf8'))
        password = m.hexdigest()

        data_dic['username'] = username
        data_dic['password'] = password
        data_dic['email'] = email

        # 1.4. 資料入庫
        models.UserInfo.objects.create(**data_dic)  # 傳入所有獲取的資料

        # 1.5. 返回資料
        back_dic['url'] = '/login/'
        return JsonResponse(back_dic)
    return render(request, 'register.html')

2. 登入頁面搭建

# views.py中寫入登入以及驗證碼功能:
# 2. 登入
def login(request):
    return render(request, 'login.html')


# 3. 生成驗證碼
"""
圖片相關的模組
    pip3 install pillow
"""
from PIL import Image, ImageDraw, ImageFont

"""
Image:生成圖片
ImageDraw:能夠在圖片上亂塗亂畫
ImageFont:控制字型樣式
"""
from io import BytesIO, StringIO

"""
記憶體管理器模組
BytesIO:臨時幫你儲存資料 返回的時候資料是二進位制
StringIO:臨時幫你儲存資料 返回的時候資料是字串
"""
import random

def get_random():
    # (100, 100, 100)
    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())
    img_draw = ImageDraw.Draw(img_obj)  # 產生一個畫筆物件
    img_font = ImageFont.truetype('static/font/font.ttf', 30)  # 字型樣式 大小 字型檔案可自行百度下載

    # 隨機驗證碼  五位數的隨機驗證碼  數字 小寫字母 大寫字母
    code = ''
    for i in range(4):
        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
    # request.session['code'] = code
    io_obj = BytesIO()
    img_obj.save(io_obj, 'png')
    return HttpResponse(io_obj.getvalue())




# 新建login.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <h1 class="text-center">登入頁面</h1>
        <div class="col-md-8 col-md-offset-2">
            <form action="">
                <div class="form-group">
                    <label for="username">使用者名稱</label>
                    <input type="text" id="username" class="form-control">
                </div>
                <div class="form-group">
                    <label for="username">密碼</label>
                    <input type="password" id="password" class="form-control">
                </div>

                <div class="form-group">
                    <label for="myfile">
                        驗證碼
                    </label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" class="form-control" id="get_code">
                        </div>
                        <div class="col-md-6">
                            <img src="/get_code/" id="re_code" alt="" style="width: 445px; height: 35px;">
                        </div>
                    </div>
                </div>
                <input type="button" class="btn btn-success btn-block" value="登入">
            </form>
        </div>

    </div>
</div>
</body>
</html>


# 路由不要忘了:
    # 登入頁面
    url(r'^login/', views.login),

    # 生成驗證碼
    url(r'^get_code/', views.get_code),

3. 登入後端邏輯的實現

import hashlib
from django.conf import settings

# 封裝密碼處理功能
def get_pwd(password):
    m = hashlib.md5()
    password = password + settings.SECRET_KEY
    m.update(password.encode('utf-8'))
    return m.hexdigest()


# 補充登入具體功能:
# 2. 登入
def login(request):
    if request.method == 'POST':
        # 定義返回資料的格式
        back_dic = {'status': 200, 'msg': '登入成功', }

        # 接收引數
        username = request.POST.get('username')
        password = request.POST.get('password')
        code = request.POST.get('code')

        # 驗證引數
        if code.upper() != request.session.get('code').upper():  # .upper() 轉大寫 不區分大小寫了
            back_dic['status'] = 1004
            back_dic['msg'] = '驗證碼不正確'
            return JsonResponse(back_dic)

        if not username:
            back_dic['status'] = 1005
            back_dic['msg'] = '使用者名稱必須填寫'
            return JsonResponse(back_dic)

        # 登入邏輯
        password = get_pwd(password)  # 獲取加密之後的密碼

        # res = models.UserInfo.objects.filter(username=username, password=password).first()
        '''防止撞庫 同時查詢使用者名稱和密碼 不要只匹配一項就返回結果給使用者'''
        res = models.UserInfo.objects.filter(username=username, password=password).first()
        if not res:
            back_dic['status'] = 1006
            back_dic['msg'] = '使用者名稱或者密碼不正確'
            return JsonResponse(back_dic)

        # 記錄使用者資訊的
        request.session['username'] = username
        request.session['id'] = res.id

        back_dic['url'] = '/home/'
        return JsonResponse(back_dic)

    return render(request, 'login.html')


# 在login.html中 新增資料提交:
"""
引入標籤不要忘了:
<script src="/static/layer-v3.5.1/layer/layer.js"></script>
"""

"""body標籤內新增script標籤繫結事件:"""
<script>
    // 更換驗證碼
    $("#re_code").click(function () {
        {#var old_code = $('#re_code').attr('src');#}
        var old_code = $(this).attr('src');
        {#$('#re_code').attr('src', old_code);#}
        $(this).attr('src', old_code);

    })


    $('.btn').click(function () {
        var username = $('#username').val();
        var password = $('#password').val();
        var code = $('#get_code').val();
        // 驗證引數
        if (!username) {
            layer.msg('使用者名稱必須填寫');
            return
        }

        if (!password) {
            layer.msg('密碼必須填寫');
            return;
        }
        if (!code) {
            layer.msg('驗證碼必須填寫');
            return;
        }
        var data = {'username': username, 'password': password, 'code': code}

        // 提交ajax 請求
        $.ajax({
            url: '',
            type: 'post',
            data: data,  // 引數過多時 單獨定義變數儲存
            success: function (res) {
                console.log(res); // 檢視後端返回的資料,
                if (res.status == 200) {
                    layer.msg(res.msg, {}, function () {
                        location.href = res.url;
                    })
                } else {
                    layer.msg(res.msg)
                }
            }

        })

    })
</script>

4. 首頁建立

# 路由:
    # 首頁
    url(r'^home/', views.home),
    
# views.py補充首頁功能:
# 4. 首頁
def home(request):
    return render(request, 'home.html', locals())
    
    
# 新建home.html檔案 使用bootstrap的導航條樣式:  
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/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="#">py20BBS</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">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>


            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                {% if request.session.username %}
                    <li><a href="#">{{ request.session.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="#" data-toggle="modal" data-target=".bs-example-modal-lg">修改密碼</a></li>
                            <li><a href="#">後臺管理</a></li>
                            <li><a href="/logout/">退出系統</a></li>
                        </ul>
                    </li>
                {% else %}
                    <li><a href="/register/">註冊</a></li>
                    <li><a href="/login/">登入</a></li>
                {% endif %}

            </ul>
        </div><!-- /.navbar-collapse -->
        <div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
            <div class="modal-dialog modal-lg" role="document">
                <div class="modal-content">
                    <div class="row">
                        <h1 class="text-center">修改密碼</h1>
                        <div class="col-md-8 col-md-offset-2">
                            <div class="form-group">
                                <label for="old_pwd">
                                    原密碼:
                                </label>
                                <input type="text" id="old_pwd" class="form-control">
                            </div>
                            <div class="form-group">
                                <label for="new_pwd">
                                     新密碼:
                                </label>
                               <input type="text" id="new_pwd" class="form-control">
                            </div>
                            <div class="form-group">
                                <label for="re_pwd">確認密碼:</label>
                                <input type="text" id="re_pwd" class="form-control">
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                                <button type="button" class="btn btn-primary set_pwd">提交</button>
                            </div>
                        </div>

                    </div>
                </div>
            </div>
        </div>
    </div><!-- /.container-fluid -->
</nav>

</body>
</html>

5. 退出系統及修改密碼功能的實現

# html檔案內容在第4點 home.html檔案中

# 新增路由:
    # 退出系統
    url(r'^logout/', views.logout),

    # 修改密碼
    url(r'^set_pwd/', views.set_pwd),

    
# views.py補充功能:
# 5. 退出系統
def logout(request):
    request.session.flush()
    return redirect('/login/')


# 6. 修改密碼
def set_pwd(request):
    if request.method == 'POST':
        # 返回的是json格式的資料
        back_dic = {'status': 200, 'msg': '修改成功', 'data': {}}
        # 1. 接收引數
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        re_pwd = request.POST.get('re_pwd')

        # 驗證引數
        if not old_pwd:
            back_dic['status'] = 1008
            back_dic['msg'] = '原密碼必須填寫'
            return JsonResponse(back_dic)
        if re_pwd != new_pwd:
            back_dic['status'] = 1009
            back_dic['msg'] = '兩次密碼不一致'
            return JsonResponse(back_dic)

        # 修改密碼
        password = get_pwd(new_pwd) # 獲取加密之後的密碼
        models.UserInfo.objects.filter(pk=request.session.get('id')).update(password=password)

        return JsonResponse(back_dic)



# html檔案內容寫在第4點home.html檔案中:
<script>
    $('.set_pwd').click(function () {
        var old_pwd = $('#old_pwd').val();
        var new_pwd = $('#new_pwd').val();
        var re_pwd = $('#re_pwd').val();
        // 驗證引數
        if (!old_pwd) {
            layer.msg('原密碼必須填寫');
            return
        }

        if (!new_pwd) {
            layer.msg('新密碼必須填寫');
            return;
        }
        if (!re_pwd) {
            layer.msg('確認必須填寫');
            return;
        }
        var data = {'old_pwd': old_pwd, 'new_pwd': new_pwd, 're_pwd': re_pwd}
        // 提交ajax 請求
        $.ajax({
            url: '/set_pwd/',
            type: 'post',
            data: data,
            success: function (res) {
                console.log(res); // 檢視後端返回的資料,
                if (res.status == 200) {
                    layer.msg(res.msg, {}, function () {
                        location.reload();
                    })
                } else {
                    layer.msg(res.msg)
                }
            }

        })
    })
</script>