博客園項目開發中的難點

1.註冊視圖

通常註冊是經過form表單形式post提交數據,數據通常經過class字段過濾值看clean_data來獲取的css

過濾字段類(放在view視圖裏)html

class UserForm(forms.Form):

    user=forms.CharField(max_length=32,
                         error_messages={"required":"該字段不能爲空"},
                         label="用戶名",
                         widget=widgets.TextInput(attrs={"class":"form-control"},)
                         )
    pwd=forms.CharField(max_length=32,
                         label="密碼",
                         widget=widgets.PasswordInput(attrs={"class":"form-control"},)
                        )
    re_pwd=forms.CharField(max_length=32,
                            label="確認密碼",
                            widget=widgets.PasswordInput(attrs={"class":"form-control"},)
                           )

經過註冊的post按鈕進行相應的ajax請求從而clean_data,顯示錯誤或者是重複的字段jquery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <style>
        #avatar_img {
            margin-left: 20px;
        }

        #avatar {
            display: none;
        }

        .error {
            color: red;
        }
    </style>

</head>
<body>
<h3>註冊頁面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">

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

                {% for field in form %}
                    <div class="form-group">
                        <label for="{{ field.auto_id }}">{{ field.label }}</label>
                        {{ field }} <span class="error pull-right"></span>
                    </div>
                {% endfor %}

                <div class="form-group">
                    <label for="avatar">
                        頭像
                        <img id="avatar_img" width="60" height="60" src="/static/blog/img/default.png" alt="">
                    </label>
                    <input type="file" id="avatar" name="avatar">
                </div>

                <input type="button" class="btn btn-default reg_btn" value="submit"><span class="error"></span>

            </form>

        </div>
    </div>
</div>


<script>
    // 頭像預覽
    $("#avatar").change(function () {

        // 獲取用戶選中的文件對象
        var file_obj = $(this)[0].files[0];
        // 獲取文件對象的路徑
        var reader = new FileReader();
        reader.readAsDataURL(file_obj);
        // 修改img的src屬性 ,src=文件對象的路徑
        reader.onload = function () {
            $("#avatar_img").attr("src", reader.result)
        };

    });

    // 基於Ajax提交數據

    $(".reg_btn").click(function () {
        //console.log($("#form").serializeArray());
        var formdata = new FormData();

        var request_data = $("#form").serializeArray();
        console.log(request_data);
        $.each(request_data, function (index, data) {
            formdata.append(data.name, data.value)
        });

        formdata.append("avatar", $("#avatar")[0].files[0]);
        console.log('formdata',formdata);
        $.ajax({
            url: "",
            type: "post",
            contentType: false,
            processData: false,
            data: formdata,
            success: function (data) {
                //console.log(data);

                if (data.user) {
                    // 註冊成功
                    location.href="/login/"
                }
                else { // 註冊失敗

                    //console.log(data.msg)
                    // 清空錯誤信息
                    $("span.error").html("");
                    $(".form-group").removeClass("has-error");

                    // 展這次提交的錯誤信息!
                    $.each(data.msg, function (field, error_list) {
                        console.log(field, error_list);
                        if (field=="__all__"){
                            $("#id_re_pwd").next().html(error_list[0]).parent().addClass("has-error");
                        }
                        $("#id_" + field).next().html(error_list[0]);
                        $("#id_" + field).parent().addClass("has-error");


                    })

                }
            }
        })

    })


</script>

</body>
</html>

2.登陸視圖

form表單形式,判斷頁面的請求方式post or getgit

def login(request):
    if request.method == 'POST':
        print(2)
        response = {'user':None, 'msg':None}
        user = request.POST.get('user',None)
        print(user,'user')
        pwd = request.POST.get('pwd', None)
        valid_code = request.POST.get('valid_code', None)
        print('valid_code',valid_code)
        # print('request', request)
        check_true = request.session.get("check")
        print("check_true",check_true)
        if valid_code.upper() == check_true.upper():
            print(1)
            user = auth.authenticate(username=user,password=pwd)  # 自動去user(django自動生成)表裏去校驗
            if user:
               auth.login(request, user)
               response['user'] = user.username
            else:
                response['msg']='密碼輸入錯誤'
        else:
            response['msg']='驗證碼錯誤'
        return JsonResponse(response)
    return render(request,'login.html')

@login_required 若視圖方法嵌套此裝飾器,且setting中設置 LOGIN_URL="/login/" 進入視圖自動跳轉至登陸界面先登陸才能進入視圖ajax

 

登陸校驗也是基於ajax實現的(校驗密碼跟驗證碼)數據庫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>LOGIN</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">

</head>
<body>
     <div id="content">
         <div>
             <div id="head" class="col-md-6 col-lg-offset-3">
            <form action="">
                {% csrf_token %}
            <div class="form-group">
                <label for="user">帳號</label>
                <input type="text" id="user" class="form-control">
            </div>
            <div class="form-group">
                <label for="pwd">密碼</label>
               <input type="password" id="pwd" class="form-control">
            </div>
             <div class="form-group">
                    <label for="pwd">驗證碼</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" class="form-control" id="valid_code">
                        </div>
                        <div class="col-md-6">
                            <img width="270" height="36" id="valid_code_img" src="/get_validCode_img/" alt="">
                        </div>
                    </div>
                </div>



        <input type="button" class="btn btn-default login_btn" value="submit"><span class="error"></span>
        <a href="/register/" class="btn btn-success pull-right">註冊</a>
    </form>
        </div>
         </div>


    </div>

</body>
<script src="/static/js/jquery-3.2.1.min.js/"></script>
<script>
    $("#valid_code_img").click(function () {
        {#console.log($(this)[0]);#}

        $(this)[0].src += "?"

    });
    $('.login_btn').click(
        function () {
            $.ajax({
                url:'',
                type:'post',
                data:{
                    user:$('#user').val(),
                    pwd:$('#pwd').val(),
                    valid_code:$('#valid_code').val(),
                    csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
                },

                success: function (data) {
                console.log(data);

                if (data.user) {
                    if (location.search){
                        location.href = location.search.slice(6)
                    }
                    else {
                         location.href = "/index/"
                    }

                }
                else {
                    $(".error").text(data.msg).css({"color": "red", "margin-left": "10px"});
                    setTimeout(function(){
                         $(".error").text("");
                    },1000)

                }
            }
                })

        })




</script>
</html>

登陸的驗證碼生成django

隨機數生成字母與數字結合的驗證碼(字體設置),顏色是基於(255,255,255)隨機生成,經過pillow(PIL)生成驗證碼圖片,並經過session存儲傳輸校驗。json

def create_img(request):
    img = Image.new('RGB',(270,40),color=color_yeild())
    draw = ImageDraw.Draw(img)
    kumo_font = ImageFont.truetype('static/font/kumo.ttf',size=32)
    check_digit = ''
    for i in range(5):
        random_num = str(random.randint(0,9))
        random_low_alpha = chr(random.randint(95, 122))
        random_upper_alpha = chr(random.randint(65, 90))
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        draw.text((i*50+20,5),random_char,color_yeild(),kumo_font)
        check_digit += random_char
    # print('check_digit',check_digit)
    request.session["check"] = check_digit




    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()


    # with open('wudi.png','wb') as f:
    #     img.save(f,'png')
    # f = open('wudi.png','rb')
    # import json
    # data = json.dumps(img)
    return HttpResponse(data)
# 隨機生成顏色
def
color_yeild(): result = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) return result

 

3.註銷視圖

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

經過超連接跳轉的方式進入視圖bootstrap

 <ul class="nav navbar-nav navbar-right">

                {% if request.user.is_authenticated %}
                    <li><a href="#"><span id="user_icon"
                                          class="glyphicon glyphicon-user"></span>{{ request.user.username }}</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="#">修改密碼</a></li>
                            <li><a href="#">修改頭像</a></li>
                            <li><a href="/cn_backend/">管理</a></li>
                            <li><a href="/logout/">註銷</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                        </ul>
                    </li>

                {% else %}
                    <li><a href="/login/">登陸</a></li>
                    <li><a href="/register/">註冊</a></li>
                {% endif %}

 

4.home_site視圖

經過正則分組獲取相應的條件瀏覽器

 re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site),

傳進視圖函數內

進行各方面判斷

def home_site(request, username, **kwargs):
    print("usename1", username)
    user = UserInfo.objects.filter(username=username).first()
    if not user:
        return HttpResponse('404')
    blog = user.blog
    article_list = Article.objects.filter(user=user)
    # article_list = models.Article.objects.filter(user=user)

    if kwargs:
        print("kwargs",kwargs)
        condition = kwargs.get("condition")
        param = kwargs.get("param")  # 2012-12

        if condition == "category":
            print(11111111111111111111111111111)
            article_list = article_list.filter(category__title=param)
        elif condition == "tag":
            print(222222222222222222222222222222)
            article_list = article_list.filter(tags__title=param)
        else:
            year, month = param.split("/")
            article_list = article_list.filter(create_time__year=year, create_time__month=month)
    return render(request,"home_site.html",{"username": username, "blog": blog, "article_list": article_list,})

5.點贊視圖

點贊視圖是基於ajax進行數據庫判斷是否登陸用戶已經進行過點贊操做(每篇文章都有相應的點贊操做)

<script>
            // 點贊請求
            $("#div_digg .action").click(function () {
                var is_up = $(this).hasClass("diggit");


                $obj = $(this).children("span");

                $.ajax({
                    url: "/digg/",
                    type: "post",
                    data: {
                        "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),   //ajax操做在上面創建csrf(位置均可以,form,div)
                        "is_up": is_up,
                        "article_id": "{{ article_obj.pk }}",
                    },
                    success: function (data) {
                        console.log(data);

                        if (data.state) {
                            var val = parseInt($obj.text());
                            $obj.text(val + 1);
                        }
                        else {
                            var val = data.handled ? "您已經推薦過!" : "您已經反對過!";   //三元表達式 if 條件?若是成立就是冒號前的,反之冒號後面的
                            $("#digg_tips").html(val);

                            setTimeout(function () {
                                $("#digg_tips").html("")
                            }, 1000)

                        }

                    }
                })

            })

視圖傳出布爾數據來判斷是否點贊過

def digg(request):
    """
    點贊視圖
    :param request:
    :return:
    """
    import json
    if request.is_ajax():
        print("點贊", request.POST)
        is_up = json.loads(request.POST.get("is_up"))   # ajax傳輸過來是網頁獲取爲布爾,傳輸自動json過,因此須要json反解碼
        article_id = request.POST.get("article_id")
        user_id = request.user.pk
        obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=article_id).first()
        print("objqueryset", obj)
        response = {"state":True}
        if not obj:
            art = ArticleUpDown.objects.create(user_id=user_id, is_up=is_up, article_id=article_id)
            queryset1 = Article.objects.filter(pk=article_id)
            print("queryset", queryset1)
            if is_up:
                queryset1.update(up_count=F("up_count")+1)
                print(1111111111111111111111111111)
            else:
                queryset1.update(down_count=F("down_count")+1)
                print(1111111111111111111111111111)
        else:
            response["state"] = False
            response["handled"] = obj.is_up
            return JsonResponse(response)

 

6.評論視圖

評論也是基於點擊事件的ajax請求

   // 評論請求
            var pid = "";

            $(".comment_btn").click(function () {

                var content = $("#comment_content").val();

                if (pid) {
                    var index = content.indexOf("\n");
                    content = content.slice(index + 1)
                }


                $.ajax({
                    url: "/comment/",
                    type: "post",
                    data: {
                        "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
                        "article_id": "{{ article_obj.pk }}",
                        "content": content,
                        pid: pid
                    },
                    success: function (data) {

                        console.log(data);

                        var create_time = data.create_time;
                        var username = data.username;
                        var content = data.content;

                        var s = `
                           <li class="list-group-item">
                              <div>

                                  <span>${create_time}</span>&nbsp;&nbsp;
                                  <a href=""><span>${username}</span></a>

                              </div>
                              <div class="comment_con">
                                  <p>${content}</p>
                              </div>

                            </li>`;

                        $("ul.comment_list").append(s);

                        // 清空評論框
                        pid = "",
                                $("#comment_content").val("");

                    }
                })


            });

下面的視圖函數包括評論郵件部分的內容,郵件部分代碼邏輯正確可是實現不了

def comment(request):
    """
    提交評論視圖函數
    功能:
    1 保存評論
    2 建立事務
    3 發送郵件
    :param request:
    :return:
    """
    print(request.POST)

    article_id = request.POST.get("article_id")
    pid = request.POST.get("pid")
    content = request.POST.get("content")
    user_id = request.user.pk

    article_obj = Article.objects.filter(pk=article_id).first()

    # 事務操做
    comment_obj = Comment.objects.create(user_id=user_id, article_id=article_id, content=content,
                                                parent_comment_id=pid)
    print("comment_obj",comment_obj)
    Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)

    response = {}

    response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")
    response["username"] = request.user.username
    response["content"] = content

    # 發送郵件

    from django.core.mail import send_mail
    from blog_project import settings
    #send_mail(1,2,"473450296@qq.com",["473450296@qq.com"], fail_silently=False)

    # send_mail(
    #     "您的文章%s新增了一條評論內容"%article_obj.title,
    #     content,
    #     settings.EMAIL_HOST_USER,
    #     # settings.EMAIL_HOST_PASSWORD,
    #     ["473450296@qq.com"]
    # )
    #
    print("settings.EMAIL_HOST_USER",settings.EMAIL_HOST_USER)
    import threading
    print("article_obj.title", article_obj.title)
    print("content", content)

    t = threading.Thread(target=send_mail, args=("您的文章%s新增了一條評論內容" % article_obj.title,
                                                 content,
                                                 settings.EMAIL_HOST_USER,
                                                 ["473450296@qq.com"])
                         )
    t.start()

    return JsonResponse(response)

郵件部分的setting

EMAIL_HOST = 'smtp.exmail.qq.com'  # 若是是 163 改爲 smtp.163.com
EMAIL_PORT = 465
EMAIL_HOST_USER = '@qq.com'           # 賬號
EMAIL_HOST_PASSWORD = ''  # 密碼 爲郵箱的受權碼
# DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
EMAIL_USE_SSL = True

7.代碼編輯器,選用固定品牌有相應的教程

8.bs4 能夠解決相應的script標籤問題

9.django視圖增長文件夾需在setting裏配置文件路徑(檢查方法看是否能夠經過路徑從瀏覽器中獲取文件)

10.csrf_token 基於post請求都會使用到他的值(常見爲ajax的post請求,能夠在form外加,也能夠在div外加,具體獲取值的方法如上述ajax請求的實例所示)

相關文章
相關標籤/搜索