• 博客园项目开发中的难点


    1.注册视图

    一般注册是通过form表单形式post提交数据,数据一般通过class字段过滤值看clean_data来获取的

    过滤字段类(放在view视图里)

    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,显示错误或者是重复的字段

    <!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 get

    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实现的(校验密码跟验证码)

    <!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>

    登录的验证码生成

    随机数生成字母与数字结合的验证码(字体设置),颜色是基于(255,255,255)随机生成,通过pillow(PIL)生成验证码图片,并通过session存储传输校验。

    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/')

    通过超链接跳转的方式进入视图

     <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("
    ");
                        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请求的实例所示)

  • 相关阅读:
    前端 “一键换肤“ 的 N 种方案及css中var()和:root用法
    给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效
    Python三方模块
    Lazarus+LAMW强制APP屏幕方向
    定制lazarus compiler config
    CentOS8的网络IP配置详解
    mongoDB导入导出
    离线安装docker并导入导出镜像
    Docker初级实战
    dwm 美化
  • 原文地址:https://www.cnblogs.com/cjj-zyj/p/9965074.html
Copyright © 2020-2023  润新知