• 报障系统之博客主页及后台管理


    个人博客:

    url函数(路由系统):

    """baozhang URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^all/(?P<type_id>d+)/', views.index),
        url(r'^login/', views.login),
        url(r'^logout/', views.logout),
        url(r'^check_code/', views.check_code),
    
        url(r'^register/', views.register),注册页面
    
        url(r'^(?P<site>w+)/(?P<key>((tag)|(category)|(date)))/(?P<val>w+-*w*).html$', views.home_filter),#筛选
        url(r'^(?P<site>w+).html$', views.home),#个人已开通博客主页
        url(r'^(?P<site>w+)/p/(?P<nid>w+).html$', views.detail),  # 文章详细
        url(r'^(?P<site>w+)/(?P<nid>d+).html$', views.article),#评论
        url(r'^up.html$', views.up),#点赞或踩
        url(r'^lizhi-(?P<article_type_id>d+)-(?P<categpry_id>d+)-(?P<tags_id>d+).html$', views.lizhi),
        url(r'^upload/', views.upload),#上传
    
        # url(r'^openblog/', views.openblog),
        # url(r'^(w+)/', views.blog),
        url(r'^test/', views.test),
        # url(r'^(w+)/$', views.home),
        url(r'^', views.index),#个人主页
    ]

    报障系统主页

    def index(request, *args, **kwargs):
        """
        个人主页
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # print(request.path_info)  # /all/1/  /all/2/
        username = request.session.get('username')
        obj = models.UserInfo.objects.filter(username=username).values('blog__site').first()
    
    
        condition = {}
        type_id = int(kwargs.get('type_id')) if kwargs.get('type_id') else None  # 如果kwargs.get('type_id')有值时转成整型没有值等于None
        if type_id:
            condition['article_type_id'] = type_id
    
        article_list = models.Article.objects.filter(**condition)
        # article_type_id = models.IntegerField(choices=type_choices, default=None)
        type_choice_list = models.Article.type_choices  # 文章分类
        user_list = models.UserInfo.objects.filter()
        return render(
            request,
            'index.html',
            {
                'username': username,
                'obj': obj,
                'type_id': type_id,
                'type_choice_list': type_choice_list,
                'article_list': article_list,
            }
        )
    个人主页函数

    Class Form类

    注册类:

    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    from django.core.validators import RegexValidator
    from app01 import models
    
    class RegisterForm(Form):
        username = fields.CharField(
            required=True,
            widget=widgets.TextInput(
                attrs={'class':'form-control','placeholder':'用户名为6-10个字符'}
            ),
            min_length=6,
            max_length=10,
            strip=True,
            error_messages={
                'required': '用户名不能为空',
                'min_length':'用户名至少为6个字符',
                'max_length':'用户名不超过10个字符',
            },
        )
        password = fields.CharField(
            required=True,
            widget=widgets.PasswordInput(
                attrs={'class':'form-control','placeholder':'密码为8-12个字符'}
            ),
            min_length=8,
            max_length=12,
            strip=True,
            validators=[
                RegexValidator(r'((?=.*d))^.{8,12}$','必须包含数字'),
                RegexValidator(r'((?=.*[a-zA-Z]))^.{8,12}','必须包含字母'),
                # RegexValidator(r'((?=.*[^a-zA-Z0-9]))^.{8,12}','必须包含特殊字符'),
                # RegexValidator(r'^.(s){8,12}','必须包含空格'),
            ],#用于对密码的正则验证
            error_messages={
                'required': '密码不能为空',
                'min_length':'密码不能少于8个字符',
                'max_length':'密码最多为12个字符!',
            }
        )
        password_again = fields.CharField(
            required=True,
            widget=widgets.PasswordInput(
                attrs={'class':'form-control','placeholder':'密码为8-12个字符'}
            ),
            min_length=8,
            max_length=12,
            strip=True,
            error_messages={'required':'请再次输入密码!',}
        )
        nickname = fields.CharField(
            required=True,
            widget=widgets.TextInput(
                attrs={'class':'form-control','placeholder':'请输入昵称'}
            )
        )
        email = fields.EmailField(
            required=True,
            widget=widgets.TextInput(attrs={'class':'form-control','placeholder':'请输入邮箱'}),
            # strip=True,
            # error_messages={'required':'邮箱不能为空','invalid':'请输入正确的邮箱格式'},
        )
        avatar = fields.FileField(widget=widgets.FileInput(attrs={'id':'imgFile','class':'f1'}))
        code = fields.CharField(widget=widgets.TextInput(attrs={'class':'form-control','placeholder':'请输入验证码'}))
        def clean_username(self):
            #对于username扩展验证,查看是否存在
            username = self.cleaned_data['username']
            users = models.UserInfo.objects.filter(username=username).count()
            if users:#如果用户名已存在
                raise ValidationError('用户名已经存在!')
            return username
        def clean_email(self):
            #对于email的扩展验证,查看是否存在
            email = self.cleaned_data['email']
            email_count = models.UserInfo.objects.filter(email=email).count()
            if email_count:
                raise ValidationError('邮箱已经存在!')
            return email
        # def _clean_password(self):#验证两次输入密码是否一致
        #     password1 = self.cleaned_data['password']
        #     password2 = self.cleaned_data['password_again']
        #     if password1 and password2:
        #         if password1 != password2:
        #             raise ValidationError('您两次输入的密码不一致')
    
        def __init__(self,request,*args,**kwargs):#构造方法,传request参数
            super(RegisterForm,self).__init__(*args,**kwargs)#完成原有form功能以外
            self.request = request#再封装一个request
    
        def clean_code(self):
            input_code = self.cleaned_data['code']
            session_code = self.request.session.get('code')#session取验证码
            if input_code.upper() == session_code.upper():#验证相等时
                return input_code#
            raise ValidationError('验证码错误')
    
        def clean(self):  # 验证两次输入密码是否一致
            p1 = self.cleaned_data.get('password')
            p2 = self.cleaned_data.get('password_again')
            if p1 == p2:
                # return self.cleaned_data
                return None
            # else:
            #     raise ValidationError('密码不一致')
            self.add_error("password_again",ValidationError('密码不一致'))
    
                # except ValidationError as e:
                # self.add_error(name, e)
        # def clean(self):
        #     #基于form对象的验证,字段全部验证通过会调用clean函数验证
        #     self._clean_password()#调用函数
        #     p1 = self.cleaned_data['password']
        #     p2 = self.cleaned_data['password_again']
        #     return p2
    
        # def clean_password(self):
        #     p1 = self.cleaned_data['password']
        #     p2 = self.cleaned_data['password_again']
            return p2
    RegisterForm类(加一个构造方法)

    登录类:

    class LoginForm(forms.Form):
        """用户登录form验证"""
        username = fields.CharField(
            required=True,
            widget=widgets.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入用户名'}),
            min_length=6,
            max_length=10,
            strip=True,
            error_messages={'required': '用户名不能为空', }
        )
        password = fields.CharField(
            required=True,
            widget=widgets.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入密码'}),
            max_length=12,
            min_length=8,
            strip=True,
            error_messages={'required': '密码不能为空', }
        )
    
        def clean(self):
            username = self.cleaned_data.get('username')
            password = self.cleaned_data.get('password')
            user_list = models.UserInfo.objects.filter(username=username).first()
            if username and password:
                if not user_list:
                    raise ValidationError('用户名不存在,请重新输入')
                elif password != user_list.password:
                    raise ValidationError('密码错误')
    LoginForm类

    用户登录视图函数

    # 用户登录
    def login(request):  # GET请求
        """
        用户登录
        :param request:
        :return:
        """
        if request.method == "GET":
            obj = LoginForm()
            return render(request, 'login.html', {'obj': obj})
        else:
            # print(request.POST)
    
            # obj = LoginForm(request.POST)
    
            # errors = {}
            # print(obj.errors)
            # print(obj)
            # print(request.session)
            # if obj.is_valid():
            input_code = request.POST.get('code')
            # print(input_code)
            session_code = request.session.get('code')
            if input_code.upper() == session_code.upper():  # 判断验证码是否正确
                username = request.POST.get('username')
                user_list = models.UserInfo.objects.filter(username=username).first()
                print(user_list)
                if user_list:
                    password = request.POST.get('password')
                    if user_list.password == password:
                        request.session['is_login'] = 'true'
                        request.session['username'] = user_list.username
                        return redirect('/')
                    else:
                        msg = '密码错误'
                        obj = LoginForm(request.POST)
                        return render(request, 'login.html', {'msg': msg, 'obj': obj})
                else:
                    msg = '该账号不存在'
                    obj = LoginForm(request.POST)
                    return render(request, 'login.html', {'msg': msg, 'obj': obj})
            else:
                msg = '验证码错误'
                obj = LoginForm(request.POST)
                return render(request, 'login.html', {'msg': msg, 'obj': obj})
                #         if request.POST.get('auto_login'):
                #             request.session.get_expiry(60*60*24*24)
                #         # request.session['is_login'] = 'true'
                #         # request.session['username'] = data.get('username')
                #         print(request.session['username'])
                #         print('123')
                #         return redirect('/')
                #     else:
                #         errors['code'] = '请输入正确的验证码'
                #         return render(request,'login.html',{'obj':obj,'errors':errors})
                # return render(request,'login.html',{'obj':obj})
    login 用户登录

    退出登录:

    def logout(request):
        """
        用户退出登录
        :param request:
        :return:
        """
        try:
            # 删除is_login对应的value值
            del request.session['is_login']
            del request.session['username']
        except KeyError:
            pass
        return redirect('/login/')
    #验证码
    logout(删除session里的值)

    获取验证码:

    #验证码
    def check_code(request):
        """
        #读取硬盘中的文件,在页面显示
        # f = open('static/images/aa.png','rb')
        # data = f.read()
        # f.close()
        # return HttpResponse(data)
        #先写到本地,再读出到页面
        # from PIL import Image
        # f = open('code.png','wb')
        # img = Image.new(mode='RGB',size=(120,30),color=(255,255,255))
        # img.save(f,'png')
        # f.close()
        #
        # f = open('code.png','rb')
        # data = f.read()
        # f.close()
        #内存开辟一块空间
        from PIL import Image,ImageDraw,ImageFont
        from io import BytesIO
        f = BytesIO()
        img = Image.new(mode='RGB',size=(120,30),color=(255,255,255))#图片对象
        draw = ImageDraw.Draw(img,mode='RGB')#画笔对象
        #画点
        draw.point([10,10],fill="red")
        draw.point([30,10],fill="red")
        #画线
        draw.line((15,10,50,50),fill='red')
        draw.line((45,20,100,100),fill=(0,255,0))
        #画圆圈
        draw.arc((0,0,30,30),0,360,fill="red")
        #写文本内容
        # draw.text([0,0],'python',"red")
    
        # font = ImageFont.truetype("kumo.ttf",28)
        # draw.text([0,0],'python',(0,255,0),font=font)
        import random #生成随机数
        # char_list = []
        # for i in range(5):
        #     char = chr(random.randint(65,90))
        #     char_list.append(char)
        # ''.join(char_list)
        # v = ''.join([chr(random.randint(65,90)) for i in range(5)])
        char_list = []
        for i in range(5):
            char = chr(random.randint(65,90))
            char_list.append(char)#保存写的随机字符
            font = ImageFont.truetype("kumo.ttf",28)
            draw.text([i*24,0],char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
        # code = ''.join(char_list)
        img.save(f,'png')
        data = f.getvalue()#读取内存里的值
    
        code = ''.join(char_list)
        print(request.session)#<django.contrib.sessions.backends.db.SessionStore object at 0x00000258DB88DC88>
        request.session['code'] = code#保存在session里
        """
        from io import BytesIO
        from utils.random_check_code import rd_check_code
        stream = BytesIO()
        img, code = rd_check_code()
        img.save(stream, 'png')
        # data = stream.getvalue()
        request.session['code'] = code
        return HttpResponse(stream.getvalue())
    check_code获取验证码

    用户注册时上传头像:

    import os
    #用户上传图片
    def upload(request):
        print(request.POST, request.FILES)
        file_obj = request.FILES.get('imgUrl')  #取文件时,需以FILES获取文件数据
        file_path = os.path.join('static/img/', file_obj.name)
        print(file_path)
        with open(file_path, 'wb') as f:  # 以wb方式写入到指定目录(bytes格式写入) # 写字节方式打开空文件,拼接文件路径
            for trunk in file_obj.chunks():  # 写入到指定目录
                f.write(trunk)
        return HttpResponse("/" + file_path)
    upload用户上传头像

    用户注册:

    def register(request):
        """
        用户注册
        :param request:
        :return:
        """
        if request.method == "GET":
            obj = RegisterForm(request)
            return render(request, 'register.html', {'obj': obj})
        else:
            # 验证码
            obj = RegisterForm(request, request.POST, request.FILES)
            if obj.is_valid():
                print(type(obj.cleaned_data))
                dict = {}
                dict['username'] = obj.cleaned_data['username']
                dict['password'] = obj.cleaned_data['password']
                dict['nickname'] = obj.cleaned_data['nickname']
                dict['email'] = obj.cleaned_data['email']
                dict['avatar'] = obj.cleaned_data['avatar']
                models.UserInfo.objects.create(**dict)
                return redirect('/')
            else:
                # print(obj.errors['__all__'])
                # print(obj.errors[NON_FIELD_ERRORS])
                """
                <ul class="errorlist nonfield"><li>密码不一致</li></ul>
                <ul class="errorlist nonfield"><li>密码不一致</li></ul>
               """
                # obj.errors是一个字典
                # - 对于Form组件错误信息
                """
                {
                    __all__: [错误1,错误2]
                user: [错误1,错误2]
                password: [错误1,错误2]
                }
                """
    
            return render(request, 'register.html', {'obj': obj})
    用户注册函数(form验证)

    个人博客主页:

    def home(request,site):
        """
        #个人博客主页
        :param request:
        :param site:
        :return:
        """
        # condition= {}
        # type_id = int(kwargs.get('type_id')) if kwargs.get('type_id') else None
        # if type_id:
        #     condition['article_type_id'] = type_id
        # type_choice_list = models.Article.type_choices
        blog = models.Blog.objects.filter(site=site).first()  # 创建一个博客对象
    
        if not blog:
            return redirect('/')
        # print(site)
    
        #按照:标签,分类,时间
        # 标签
        tag_list = models.Article2Tag.objects.filter(article__blog=blog).values('tag_id', 'tag__title').annotate(ct=Count('id'))
        #分类
        category_list = models.Article.objects.filter(blog=blog).values('category_id','category__title').annotate(ct=Count('nid'))#queryset[字典1,字典2......]
    
        #时间
        date_list = models.Article.objects.filter(blog=blog).extra(select={'ctime':"date_format(create_time,'%%Y-%%m')"}).values('ctime').order_by('-ctime').annotate(ct=Count('nid'))
        #文章分页
        all_count = models.Article.objects.all().count()
        page_info = PageInfo(request.GET.get('page'), all_count, 2, '/bingabcd.html', 11)
    
        article_list = models.Article.objects.all()[page_info.start():page_info.end()]
    
        # #获取时间分组
        #
        # date_list = models.Article.objects.filter(blog=blog).extra(select={'c':"date_format(create_time,'%%Y-%%m')"}).values('c').order_by('-c').annotate(ct=Count('nid'))
        """
        nid,title
        """
        return render(
            request,
            'home.html',
            {
                'site':site,#博客后缀
                'blog': blog,#博客对象
                'article_list':article_list,#文章列表
                'page_info':page_info,#分页
    
                'tag_list':tag_list,#标签
                'category_list':category_list,#分类
                'date_list':date_list,#时间
            }
        )
            # 1.当前博客的所有文章
    home个人博客主页

    个人博客文章筛选:

    #个人博客筛选
    def home_filter(request,site,key,val):
        """
        个人博客筛选
        :param request:
        :param site:
        :param key:
        :param val:
        :return:
        """
        # blog = models.Blog.objects.filter(site=site).select_related('user').first()#related_name直接连表,如果做for循环query_set对象时,减少查询次数
        # print(blog)
        # if not blog:
        #     return redirect('/')
    
        blog = models.Blog.objects.filter(site=site).first()  # 创建一个博客对象
        print(blog)
        if not blog:
            return redirect('/')
        #按照:标签,分类,时间
        #标签
        tag_list = models.Article2Tag.objects.filter(article__blog=blog).values('tag_id','tag__title').annotate(ct=Count('id'))
        print(tag_list)
        print(tag_list.query)
        #分类
        category_list = models.Article.objects.filter(blog=blog).values('category_id','category__title').annotate(ct=Count('nid'))#queryset[字典1,字典2......]
        print(category_list)
        print(category_list.query)
        #时间
        date_list = models.Article.objects.filter(blog=blog).extra(select={'ctime':"date_format(create_time,'%%Y-%%m')"}).values('ctime').order_by('-ctime').annotate(ct=Count('nid'))
        print(date_list.query)
        print('1111')
        #文章分页
        all_count = models.Article.objects.all().count()#总页数
        page_info = PageInfo(request.GET.get('page'), all_count, 2, '/bingabcd.html', 11)
        if key == 'tag':
            article_list = models.Article.objects.filter(tags__nid=val,blog=blog)[page_info.start():page_info.end()] #文章列表
            print(article_list)
            # v = models.Article.objects.filter(blog=blog,article2tag__tag__title=val)
            # print(v.query)
            # #自定义第三张表
            # #自己反向关联
            # v = models.Article.objects.filter(blog=blog,article2tag__tag=val)
            # #通过M2M字段
            # v = models.Article.objects.filter(blog=blog,tags__nid=val)
        elif key == 'category':
            article_list = models.Article.objects.filter(category_id=val,blog=blog)[page_info.start():page_info.end()] #文章列表
            print(article_list)
        else:
            # article_list = models.Article.objects.filter(create_time=val,blog=blog).all()[page_info.start():page_info.end()]#文章列表
            article_list = models.Article.objects.filter(blog=blog).extra(where=["date_format(create_time,'%%Y-%%m')=%s"],params=[val,])[page_info.start():page_info.end()]
            print(article_list)
    
    
        return render(
            request,
            'home_filter.html',
            {
                'blog':blog,
                'tag_list':tag_list,
                'category_list':category_list,
                'date_list':date_list,
                'article_list':article_list,
                'page_info':page_info
            }
        )
    home_filter个人博客筛选

    查看文章详细页:

    #查看文章详细页
    def detail(request,*args,**kwargs):#文章详细
        """
        查看文章详细页
        :param request:
        :return:
        """
        site = kwargs.get("site")
        nid = kwargs.get('nid')
        url = request.path_info
        user_id = request.session.get('user_id')
        # 博客信息
        blog = models.Blog.objects.filter(site=site).first()
        if user_id:
            userinfo = models.UserInfo.objects.filter(nid=user_id).first()
        else:
            userinfo = False
        #文章
        obj = models.Article.objects.filter(blog__site=site,nid=nid).first()
        print(obj)
        #分类列表
        category_list = models.Article.objects.filter(blog__site=site).values('category__title','category_id').annotate(c=Count('nid'))
        #标签列表
        tag_list = models.Article.objects.filter(blog__site=site).values('tags__title','tags__nid').annotate(c=Count('nid'))
        #时间列表
        date_list = models.Article.objects.filter(blog=blog).extra(select={'c':"date_format(create_time,'%%Y-%%m')"}).values('c').order_by('-c').annotate(ct=Count('nid'))
    
        comment_list = []
        com = []
        comment = enumerate(obj.comment_set.all())
        for i,j in comment:
            com = []
            com.append(i+1)
            com.append(j)
            comment_list.append(com)
        return render(
            request,
            'article_detail.html',
            {
                'url':url,
                'obj':obj,
                'blog':blog,
                'date_list':date_list,
                'category_list': category_list,
                'tag_list': tag_list,
                'userinfo':userinfo,
                'comment':comment_list,
            }
        )
    detail查看文章详细页

     文章中赞或者踩:

    待补充:

    博客系统后台管理:

    后台管理:

    组合筛选:

    第一种方式:用for循环:

    views.py

    def lizhi(request,**kwargs):
        print(kwargs)#{'article_type_id': '1', 'category_id': '1', 'tags_id': '0'}#从url传过来的数据
        condition = {}
        for k,v in kwargs.items():
            kwargs[k] = int(v)
            if v != '0':
                condition[k] = v
        print(condition)#{'article_type_id': '1', 'category_id': '1'}
        # 大分类
        type_list = models.Article.type_choices
        print(type_list)#[(1, 'Python'), (2, 'Linux'), (3, 'OpenStack'), (4, 'GoLang'), (5, 'Car')]
        #个人分类
        category_list = models.Category.objects.filter(blog_id=1)#
        print(category_list)#<QuerySet [<Category: bingabcd-Python>, <Category: bingabcd-设计模式>, <Category: bingabcd-机器人>]>
        #个人标签
        tag_list = models.Tag.objects.filter(blog_id=1)
        print(tag_list)#<QuerySet [<Tag: bingabcd-Python之路>, <Tag: bingabcd-Django>, <Tag: bingabcd-HTML>, <Tag: bingabcd-机器人>, <Tag: bingabcd-人工智能>]>
        # 对文章进行筛选
        condition['blog_id']=1
        article_list = models.Article.objects.filter(**condition)
        print(article_list)#<QuerySet [<Article: bingabcd-Python>, <Article: bingabcd-机器人>, <Article: bingabcd-Python基本数据类型>, <Article: bingabcd-Django基础>]>
        return render(request,
                      'lizhi.html',
                      {
                          'type_list':type_list,
                          'category_list':category_list,
                          'tag_list':tag_list,
                          'article_list':article_list,
                          'kwargs':kwargs
                      }
                )
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .condition a{
                display: inline-block;
                padding: 5px;
            }
            .condition a.active{
                background-color: #204d74;
                color: white;
            }
        </style>
    </head>
    <body>
        <h3>筛选</h3>
        <div class="condition">
            大大分类:
            {% if kwargs.article_type_id == 0 %}
                <a class="active" href="/lizhi-0-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">全部</a>
            {% else %}
                <a href="/lizhi-0-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">全部</a>
            {% endif %}
    
            {% for row in type_list %}
                {% if row.0 == kwargs.article_type_id %}
                    <a class="active" href="/lizhi-{{ row.0 }}-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">{{ row.1 }}</a>
                {% else %}
                    <a href="/lizhi-{{ row.0 }}-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">{{ row.1 }}</a>
                {% endif %}
            {% endfor %}
            <div>
                个人分类
                <a href="#">全部</a>
                {% for row in category_list %}
                    <a href="{{ row.nid }}">{{ row.title }}</a>
                {% endfor %}
            </div>
    
            <div>
                个人标签
                <a href="#">全部</a>
                {% for row in tag_list %}
                    <a href="{{ row.nid }}">{{ row.title }}</a>
                {% endfor %}
            </div>
    
            <div>
                <h3>结果</h3>
                {% for row in article_list %}
                    <h4><a href="#">{{ row.title }}</a></h4>
                    <div>{{ row.summary }}</div>
                {% endfor %}
            </div>
    {#        大大分类:#}
    {#        {% if kwargs.article_type_id == 0 %}#}
    {#            <a class="active" href="/lizhi-0-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">全部</a>#}
    {#        {% else %}#}
    {#            <a href="/lizhi-0-{{ kwargs.category_id }}"></a>#}
    {#        {% endif %}#}
            
        </div>
    </body>
    </html>
    组合搜索.html

    组合搜索功能还未完善:

    #URL
    #urls.py
    
    # url(r'^screen-(?P<article_type_id>d+)-(?P<category_id>d+)-(?P<article2tag__tag_id>d+).html$', views.screen),
    url(r'^screen-(?P<article_type_id>d+)-(?P<category_id>d+)-(?P<tags__nid>d+).html$', views.screen),
    
    #视图函数
    #views.py
    
    def screen(request,**kwargs):
        # print(kwargs)
        condition = {}
        for k,v in kwargs.items():
            kwargs[k] = int(v)
            if v != '0':
                condition[k] = v
        print(condition)
    
        #大分类
        type_list = models.Article.type_choices
    
        #个人分类
        catagory_list = models.Category.objects.filter(blog_id=1)
    
        #个人标签
        tag_list = models.Tag.objects.filter(blog_id=1)
    
        #进行筛选
        condition['blog_id']=1
        article_list = models.Article.objects.filter(**condition)
    
        return render(request,'screen.html',{
            'type_list':type_list,
            'catagory_list':catagory_list,
            'tag_list':tag_list,
            'article_list':article_list,
            'kwargs':kwargs,
        })
        
    
    #模板语言
    #screen.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .condition a{
                display: inline-block;
                padding: 5px;
            }
            .condition a.active{
                background-color: #0a386a;
                color: white;
            }
        </style>
    </head>
    <body>
    
        <h3>筛选</h3>
        <div class="condition">
            大大分类:
            {% if kwargs.article_type_id == 0 %}
                <a class="active" href="/screen-0-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">全部</a>
            {% else %}
                <a href="/screen-0-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">全部</a>
            {% endif %}
            {% for row in type_list %}
                {% if row.0 == kwargs.article_type_id %}
                    <a class="active" href="/screen-{{ row.0 }}-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">{{ row.1 }}</a>
                {% else %}
                    <a href="/screen-{{ row.0 }}-{{ kwargs.category_id }}-{{ kwargs.tags__nid }}.html">{{ row.1 }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div class="condition">
            个人分类:
            <a href="#">全部</a>
            {% for row in catagory_list %}
                <a href="{{ row.nid }}">{{ row.title }}</a>
            {% endfor %}
        </div>
        <div class="condition">
            个人标签:
            <a href="#">全部</a>
            {% for row in tag_list %}
                <a href="{{ row.nid }}">{{ row.title }}</a>
            {% endfor %}
        </div>
        <h3>结果</h3>
        {% for row in article_list %}
            <div>
                <h4><a href="#">{{ row.title }}</a></h4>
                <div>{{ row.summary }}</div>
            </div>
        {% endfor %}
    </body>
    </html>
    
    报障系统后台管理组合筛选
    报障系统后台管理组合筛选

    第二种方式:用simple_tag+filter

    KindEditor上传图片:

    参考文档:KindEditor

    #URL路由
    #urls.py
    url(r'^upload_img.html$', views.upload_img),
    
    #视图函数
    #views.py
    def upload_img(request):
        import os
        # print(request.POST, request.FILES)
        # upload_type = request.GET.get('dir')
        # 根据上传得文件类型控制上传得文件目录
    
        file_obj = request.FILES.get('imgFile')
        file_path = os.path.join('static/img',file_obj.name)
        with open(file_path,'wb') as f:
            for chunk in file_obj.chunks():
                f.write(chunk)
    
        dic = {
            'error':0,
            'url':'/'+file_path,
            'message':'错误了...'
        }
        import json
        return HttpResponse(json.dumps(dic))
    
    
    #模板语言
    #editor.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        <form method="POST" action="/editor.html" novalidate>
        {#如果不加novalidate,{{ obj.content }}会报错#}
            <p>
                文章标题
                {{ obj.title }}
            </p>
            {% csrf_token %}
            <div>
                <div>文章内容</div>
                <div>
                    {{ obj.content }}
                </div>
            </div>
            <input type="submit" value="提交">
        </form>
    
        <script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>
        <script>
            KindEditor.create("#i1",{
                 "700px",
                height: "300px",
                uploadJson: '/upload_img.html',
                extraFileUploadParams: {
                    "csrfmiddlewaretoken":"{{ csrf_token }}"  
                {# 需要添加CSRF验证#}
                }
            })
        </script>
    </body>
    </html>
    
    KindEditor上传图片
    KindEditor上传图片

    补充:

    文件上传其实内部就是iframe+form 伪Ajax操作
    input type='file' name='imgFile' 提交
    可以通过filePostName 更改默认name属性:
    filePostName: 'fafafa'

    BeautifulSoup模块基本使用:

    beautifulsoup4的基本使用
    安装:
    pip3 install beautifulsoup4
    导入模块:
    from bs4 import BeautifulSoup
    
    valid_tag = [] #只能设置标签名的白名单
    valid_tag = {} #既能加标签名又能加标签的属性的白名单
    
    tag.name 获取标签名
    
    soup.find() #查找第一个标签
    soup.find_all() #查找所有的p标签
    
    tag.clear() #清除标签中的内容
    tag.decompose() #清空标签中的内容并且删除标签
    
    decode() soup对象转换成字符串
    encode() soup对象转换成字节
    
    
    
    #示例:
    
    content = """
    <p id='i1' a='123' b='999'>
        <script>alert(123)</script>
    </p>
    <p id='i2'>
        <div>
            <p>asfjldjf</p>
        </div>
        <img id='i3' src="/static/imglang.jpg" alt="" />
    </p>
    """
    
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(content,'html.parser')
    
    
    #设置名叫valid_tag的白名单:
    
    # valid_tag = ['p','img','div']  #只能放置标签名,列表形式
    
    valid_tag = {                    #既能加标签名又能加标签的属性,字典形式。
        'p':['class','id'],
        'img':['src'],
        'div':['class']
    }
    
    
    # v=soup.find(name='p',attrs={'id':'i2'}) #查找第一个p标签,并且id是i2
    # print(v)
    
    # tag = soup.find(name='p') #查找第一个p标签,生成的是对象的形式,可以通过“.”形式继续查找
    # sc=tag.find('script') 
    # print(sc)
    
    # v=soup.find_all(name='p') #查找所有的p标签
    # print(v)
    
    # tags = soup.find_all() #查找所有的标签
    # for tag in tags:   #tag.name是标签名
    #     if tag.name not in valid_tag: #如果标签名不在白名单中则情况标签中的内容
    #         tag.clear()
    
    tags = soup.find_all()
    for tag in tags:
        if tag.name not in valid_tag:
            tag.decompose() #删除不再白名单中的标签
        if tag.attrs:
            for k in list(tag.attrs.keys()): #{id:'i1',a=123,b=999}
                if k not in valid_tag[tag.name]:
                    del tag.attrs[k]
    
    content_str=soup.decode()  #去掉特殊标签后,拿到它的字符串
    print(content_str) #打印过滤后的标签字符串
    
    beautifulsoup4的基本使用
    beautifulsoup4的基本使用

    基于KindEditor和BeautifuSoup实现防止XSS攻击:

    基于KindEditor和BeautifuSoup实现防止XSS攻击
    
    #URL路由系统
    #urls.py
    url(r'^editor.html$', views.editor),
    #可视化编辑器
    
    url(r'^see.html$', views.see),
    #查看可视化编辑器生成的样式
    
    url(r'^upload_img.html$', views.upload_img),
    #上传图片
    
    
    #视图函数
    #views.py
    
    CONTENT = ""
    from app01.forms import ArticleForm
    def editor(request):
        if request.method=="GET":
            obj = ArticleForm()
            return render(request,'editor.html',{'obj':obj})
        else:
            obj = ArticleForm(request.POST)
            if obj.is_valid():
                content = obj.cleaned_data['content']
                global CONTENT
                CONTENT = content
                print(content)
                return HttpResponse("...")
    
    def see(request):
        return render(request,'see.html',{'con':CONTENT})
    
    def upload_img(request):
        import os
        # print(request.POST, request.FILES)
        # upload_type = request.GET.get('dir')
        # 根据上传得文件类型控制上传得文件目录
    
        file_obj = request.FILES.get('imgFile')
        file_path = os.path.join('static/img',file_obj.name)
        with open(file_path,'wb') as f:
            for chunk in file_obj.chunks():
                f.write(chunk)
    
        dic = {
            'error':0,
            'url':'/'+file_path,
            'message':'错误了...'
        }
        import json
        return HttpResponse(json.dumps(dic))
    
        
    #模板语言
    #editor.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        <form method="POST" action="/editor.html" novalidate>
    {#        如果不加novalidate,{{ obj.content }}会报错#}
            <p>
                文章标题
    {#            <input type="text" name="title">#}
                {{ obj.title }}
            </p>
    {#        <p>#}
    {#            选择分类#}
    {#            <select name="" id="">#}
    {##}
    {#            </select>#}
    {#        </p>#}
    {#        <p>#}
    {#            选择标签#}
    {#            <input type="checkbox">#}
    {#            <input type="checkbox">#}
    {#            <input type="checkbox">#}
    {#            <input type="checkbox">#}
    {#        </p>#}
            {% csrf_token %}
            <div>
                <div>文章内容</div>
                <div>
    {#                <textarea name="content" id="i1" cols="30" rows="10"></textarea>#}
                    {{ obj.content }}
                </div>
            </div>
            <input type="submit" value="提交">
        </form>
    
        <script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>
        <script>
            KindEditor.create("#i1",{
                 "700px",
                height: "300px",
    {#            items: [ 'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',],#}
    {#            noDisableItems: ['undo','redo'],#}
    {#            designMode: false,#}
    {#            resizeType:1,#}
                uploadJson: '/upload_img.html',
                extraFileUploadParams: {
                    "csrfmiddlewaretoken":"{{ csrf_token }}"
                {# 需要添加CSRF验证#}
                }
            })
        </script>
    </body>
    </html>
    
    
    #Form组件
    #forms.py
    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    
    class ArticleForm(Form):
        title = fields.CharField(max_length=64)
        content  = fields.CharField(
            widget=widgets.Textarea(attrs={'id':'i1'})
        )
    
        def clean_content(self):
            from bs4 import BeautifulSoup
    
            valid_tag = {
                'p': ['class', 'id'],
                'img': ['src'],
                'div': ['class']
            }
    
            old=self.cleaned_data['content']
            soup = BeautifulSoup(old, 'html.parser')
    
            tags = soup.find_all()
            for tag in tags:
                if tag.name not in valid_tag:
                    tag.decompose()  # 删除不再白名单中的标签
                if tag.attrs:
                    for k in list(tag.attrs.keys()):  # {id:'i1',a=123,b=999}
                        if k not in valid_tag[tag.name]:
                            del tag.attrs[k]
    
            content_str = soup.decode()
            return content_str
    
    防止XSS攻击
    防止XSS攻击
    补充:
    
    防止XSS攻击为什么不用黑名单,要用白名单?
    使用白名单过滤html标签比黑名单操作起来更简单,把攻击锁定在自己可控制范围内。

    参考博客:http://www.cnblogs.com/wupeiqi/articles/6283017.html

  • 相关阅读:
    洛谷【P1177】【模板】归并排序
    洛谷【P1177】【模板】快速排序
    洛谷【P1104】生日(冒泡排序版)
    洛谷【P1104】生日(插入排序版)
    洛谷【P1104】生日(选择排序版)
    BZOJ5443:[CEOI2018]Lottery
    ReactNative---ref的用法和技巧
    ios---运用MJRefresh组件设置下拉刷新
    ReactNative---setState与性能的平衡
    ios---设置UITabBarController的字体颜色和大小
  • 原文地址:https://www.cnblogs.com/bingabcd/p/7209073.html
Copyright © 2020-2023  润新知