zoukankan      html  css  js  c++  java
  • blog项目知识点梳理

    1.获取图片验证码:
    def get_validCode_img(request):
    
    
    
        # 方式1:
        # import os
        # path= os.path.join(settings.BASE_DIR,"blog","static","img","egon.jpg")
        #
        # with open(path,"rb") as f:
        #     data=f.read()
    
        # 方式2:
        # from  PIL import Image
        #
        # img=Image.new(mode="RGB",size=(120,40),color="green")
        #
        # f=open("validCode.png","wb")
        # img.save(f,"png")
        #
        # with open("validCode.png","rb") as f:
        #     data=f.read()
    
        # 方式3:
        # from io import BytesIO
        #
        # from PIL import Image
        # img = Image.new(mode="RGB", size=(120, 40), color="blue")
        # f=BytesIO()
        # img.save(f,"png")
        # data=f.getvalue()
        # return HttpResponse(data)
    
        # 方式4 :
    
        from io import BytesIO
        import random
    
        from PIL import Image,ImageDraw,ImageFont
        img = Image.new(mode="RGB", size=(120, 40), color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
    
        draw=ImageDraw.Draw(img,"RGB")
        font=ImageFont.truetype("blog/static/font/kumo.ttf",25)
    
        valid_list=[]
        for i in range(5):
    
            random_num=str(random.randint(0,9))
            random_lower_zimu=chr(random.randint(65,90))
            random_upper_zimu=chr(random.randint(97,122))
    
            random_char=random.choice([random_num,random_lower_zimu,random_upper_zimu])
            draw.text([5+i*24,10],random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
            valid_list.append(random_char)
    
    
        f=BytesIO()
        img.save(f,"png")
        data=f.getvalue()
    
        valid_str="".join(valid_list)
        # print(valid_str)
    
        request.session["keepValidCode"]=valid_str
    
        return HttpResponse(data)
        
    2.点击验证码图片刷新效果
    $('.validCode_img').click(function () {
            console.log(this)
            this.src+="?"
        })
    
    3.注册form组件注意事项
    if form.is_valid():   
        
        username=form.cleaned_data['username']   #如果form过滤验证成功了 就直接在form.cleaned_data内取值就行,不必从request.POST中取值
        password=form.cleaned_data['password']
        email=form.cleaned_data['email']
        tel=form.cleaned_data['tel']
        avatar = request.FILES.get("avatar")
        if not avatar:
            #用户注册时未选取头像,那么在创建新用户时不用创建头像字段,因为在models中已经设置了默认值,不然在数据库中存的会是空
            models.UserInfo.objects.create_user(username=username,password=password,email=email,telephone=tel)   
        else:
            models.UserInfo.objects.create_user(username=username,password=password,email=email,telephone=tel,avatar=avatar)
    form组件的局部钩子返回值 : return self.cleaned_data['xxx']    
              全局猴子返回值 : return self.cleaned_data
              #钩子函数中在 clean_data 取值时, 要用 get方法
              
    4.头像预览
    
    <div class="form-group" id="i2">
    
        {#      注意下面img与input 标签的前后顺序,如颠倒会出现点击图片不出现选择图片窗口              #}
                <label for="avatar">头像</label>
                <img src="/static/img/default.png/" alt="" class="c1" id="i1">
                <input type="file" id="avatar" class="c1">
     </div>
        
    $("#avatar").change(function () {
    
        var ele_file=$(this)[0].files[0];  //$(this)[0]和this 一样
        var reader=new FileReader();
        reader.readAsDataURL(ele_file);
        reader.onload=function () {
            $("#i1")[0].src=this.result
        }
     });
        
    5.注册时返回的错误信息的处理
        var errors_msg=data1['errors_msg'];
        $.each(errors_msg,function (i,v) {
        {#                        console.log(i,v);#}
            var ele=$('<span>');
            ele.html(v[0]).addClass('pull-right').css('color','red');
            $('#'+i).after(ele).parent().addClass('has-error')
            if(i=='__all__'){
            
            $('#repassword').after(ele).parent().addClass('has-error')
        }
        })
        
    6.ajax在提交二进制数据时用formData
        var formData=new FormData();
        formData.append('username',$('#username').val());
        formData.append('avatar',$('#avatar')[0].files[0]);
    
        $.ajax({
            url:'/reg/',
            type:'POST',
            data:formData,
            contentType:false,
            processData:false,
            headers:{"X-CSRFToken":$.cookie('csrftoken')},   #需要引用  <script src="/static/js/jquery.cookie.js"></script>  
                                                             #有时引用的cookie.js文件没有效果,那就换成 cdn 引用
    
    7.url路由分发与url反向解析
    
        根路径配置:  url(r'^$', views.index),   url是ip+端口时,没有路径,执行index视图函数
        
        路由分发:
        '''
            Including another URLconf
            1. Import the include() function: from django.conf.urls import url, include
            2. Add a URL to urlpatterns:  url()
        '''
        from django.conf.urls import url, include
        
        url(r'^blog/',include('blog.urls')),
        
        反向解析:
        
        url(r'^(?P<user>.*)/$',views.person_site,name='aaa'),
        
        <a href="{% url 'aaa' request.user.username %}"></a>    #注意 在url反向解析时,如需要参数就必须传
                
            
    8.首页的左侧菜单:
    index.html
        {% for site_category in site_category_list %}
            <div class="panel panel-success">
                <div class="panel-heading site_category">{{ site_category.name }}</div>
                <div class="panel-body hides">
                    {% for obj in site_category.sitearticlecategory_set.all %}
                        <a href="/cate/{{ obj.name }}/" style="text-decoration: none"><p>{{ obj.name }}</p></a>    #在点击相应的分类是显示此分类的所有文章
                    {% endfor %}
                </div>
            </div>
        {% endfor %}
    
    urls.py
        url(r'^cate/(.*)/$', views.index),
        
    views.py
        def index(request,*args):
    
            if args:
                article_list = models.Article.objects.filter(site_article_category__name=args[0])
            else:
                article_list=models.Article.objects.all()
    
            site_category_list=models.SiteCategory.objects.all()
    
            return render(request,"index.html",{'article_list':article_list,'site_category_list':site_category_list})
            
    css/js样式:
        <script>
            $('.site_category').mouseover(function () {
               console.log($(this))     
               console.log(this)        //打印两者的区别???
                $(this).next().slideDown(300)
            }).parent().mouseleave(function () {
                $(this).children('.panel-body').slideUp(300)
            })
        </script>
    
            
    9.头像图片在页面中显示的两种方式:
        <img src="/media/{{ user.user.avatar }}" width="60px" height="60px">
    
        <img src="{{ user.user.avatar.url }}" width="60px" height="60px">
        
    10.    media配置:
    settings.py
        MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media","uploads")
        MEDIA_URL="/media/"
        
    urls.py
        url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
        
    用处:
         -----      avatar = models.FileField(verbose_name='头像', upload_to='avatar', default="/avatar/default.png")
                    会把接收的文件放在media指代的路径与upload_to的拼接:
                        BASE_DIR/blog/media/uploads/avatar/  xxx图片
                    
                    avatar字段在数据库保存的是:avatar/a.png
                    
         ------     
                     在页面中显示  <img src="/media/avatar/a.png">    
        
        
    11.    auth模块:     http://www.cnblogs.com/liuwei0824/p/7772525.html
    
    12. 个人首页:
      时间归档:
       date_list=models.Article.objects.filter(user=user_obj).extra(select={"filter_create_date":"strftime('%%Y/%%m',create_time)"}).values_list(    "filter_create_date").annotate(Count("nid"))
        
      园龄:自定义过滤器用当前的时间对象-创建的时间对象
            注意:在引用自定义过滤器时 要在body标签下  其他位置浏览器会出现小错误
      
      标签与分类归档有两种方式处理:
            1. 在后端用分组聚合函数处理完成传入前端直接渲染
            2. 在后端把文章对象传给前端,在前端深度查询进行渲染
        
    
    13. 评论树:
        views.py 
        def commentTree(request,article_id):
            time_dict={}
            avatar_dict={}
            comment_all=models.Comment.objects.filter(article_id=article_id)
            for i in comment_all:
    
                avatar='/media/'+str(i.user.avatar)
                time=str(i.create_time).split('.',1)[0][:-3]
                time_dict[i.nid]=time
                avatar_dict[i.nid]=avatar
    
    
            comment_list=models.Comment.objects.filter(article_id=article_id).values('nid','user__username','user__avatar','content','parent_comment_id')
    
            for i in comment_list:
                if i['nid'] in time_dict:
                    i['create_time']=time_dict[i['nid']]
                if i['nid'] in time_dict:
                    i['create_user_avatar'] = avatar_dict[i['nid']]
                i['children_list'] = []
    
            d = {}
            for i in comment_list:
                d[i['nid']] = i
    
            for i in comment_list:
                if i['parent_comment_id'] in d:
                    d[i['parent_comment_id']]['children_list'].append(i)
    
            li = []
            for i, j in d.items():
                if not j['parent_comment_id']:
                    li.append(j)
            # print(li,66666666666666)
            import json
            return HttpResponse(json.dumps(li))
    
        .html
        <h5>已发表评论(评论树):</h5>
                 <div class="comment_tree_list">
    
                 </div>    
            $.ajax({
    
    
                url:'/blog/commentTree/'+$.cookie('article_obj_nid'),
                type:'get',
                success:function (data) {
                var data=JSON.parse(data);
    
        <script>
        {#            console.log(data[1]);#}
                var s=showCommentTree(data);
                    $(".comment_tree_list").append(s);
            }
            })
    
    
    
            function showCommentTree(comment_list) {    //  comment_list: [{"content":"1","children_list":[{}]},{"content":"2"},{"content":"3"},]
                var html="";
    
                $.each(comment_list,function (i,comment_dict) {
                    var nid=comment_dict['nid'];
                    var val=comment_dict["content"];
                    var avatar=comment_dict["create_user_avatar"];
                    var create_time=comment_dict["create_time"];
                    var comment_username=comment_dict["user__username"];
                    var ssss='<div class="row comment_content_haed"><div><span> '+'<img src='+avatar+' alt="" height="25px" width="25px" style="margin-right: 5px"></span>&nbsp;&nbsp;<a href="" style="text-decoration: none" class="comment_color c1">'+comment_username+'</a><span style="margin-left: 10px">'+create_time+'</span><a title="发送站内短消息" class="sendMsg2This" href="">&nbsp;</a></div><div class="comment_content_body"><p style="margin-left: 18px">'+val+'</p></div><div class="tig_head" comment_pid='+nid+'><a class="pull-right comment_color tig reply" style="text-decoration: none">回复</a><a class="pull-right tig comment_color" style="text-decoration: none">支持({{ comment_obj.up_count }})</a></div></div><hr style="margin-right: 60px">'
                    var commnent_str= '<div class="comment"><div class="content"><span>'+ssss+'</span></div>';
    
                    if(comment_dict["children_list"]){
                        var s=showCommentTree(comment_dict["children_list"]);    // [{},{}]
                        commnent_str+=s
                    }
    
                    commnent_str+="</div>";
                    html+=commnent_str
                });
    
                return html
            }
        </script>
    
        
    14. 编辑器的防止xss攻击:用form组件过滤出敏感的标签及属性
    forms.py  引用xss
    class ArticleForm(Form):
    
        content=fields.CharField(required=True,error_messages={'required':'不能为空'},
                                  widget=widgets.Textarea(attrs={'id':'comment_content'}))
    
    
        def clean_content(self):
            from blog.plugins import xss_plugin
    
            html_str=self.cleaned_data.get("content")
            clean_content=xss_plugin.filter_xss(html_str)
            self.cleaned_data["content"]=clean_content
    
            return self.cleaned_data.get("content")
    
    def filter_xss(html_str):
        valid_tag_list = ["p", "div", "a", "img", "html", "body", "br", "strong", "b"]
    
        valid_dict = {"p": ["id", "class"], "div": ["id", "class"]}
    
        from bs4 import BeautifulSoup
    
        soup = BeautifulSoup(html_str, "html.parser")  # soup  ----->  document
    
        ######### 改成dict
        for ele in soup.find_all():
            # 过滤非法标签
            if ele.name not in valid_dict:
                ele.decompose()
            # 过滤非法属性
    
            else:
                attrs = ele.attrs  # p {"id":12,"class":"d1","egon":"dog"}
                l = []
                for k in attrs:
                    if k not in valid_dict[ele.name]:
                        l.append(k)
    
                for i in l:
                    del attrs[i]
    
        print(soup)
    
        return soup.decode()     #默认decode 格式就是utf-8        
            
    15. 后台管理:增删改查....    
    
    16. kindeditor 编辑器文本域获取焦点    ???
            
  • 相关阅读:
    odoo11 访问MSQL Server等第三发数据源
    学习 Git Rebase
    Arch Linux 启用 MTU 探测
    可控函数
    DIY:从零开始写一个 SQL 构建器
    F# 4.6 预览版正式公布
    使用 Immutable Subject 来驱动 Angular 应用
    如何对付运行时可能为 null 的 Record Type
    Angular Forms
    不要使用 JWT 进行会话管理
  • 原文地址:https://www.cnblogs.com/liuwei0824/p/8448238.html
Copyright © 2011-2022 走看看