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

个人博客:

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查看文章详细页

文章中赞或者踩:

待补充:

博客系统后台管理:

后台管理:

组合筛选:

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

报障系统后台管理组合筛选

报障系统后台管理组合筛选

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",{
            width: "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/img\lang.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",{
            width: "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

时间: 2024-10-10 15:34:25

报障系统之博客主页及后台管理的相关文章

绿色版Tomcat 启动 + 停止 + 随系统自动启动 - - 博客频道 - CSDN.NET

body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI",Tahoma,Helvetica,Sans-Serif,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5;

基于cookie的SSO单点登录系统 - waen - 博客园

原文:基于cookie的SSO单点登录系统 - waen - 博客园 利用数据库触发器实现定期自动增量更新缓存 原文地址:https://www.cnblogs.com/lonelyxmas/p/10434813.html

博客主页动态线条效果

经过一个下午你努力,我也把自己的博客主页变成了动态的效果了嘿嘿嘿. 这里声明一件事情以下内容是借鉴他人作品而写的我只是一个搬运工 借鉴博客   :https://www.cnblogs.com/panghu123/     如若侵权请告知 先插效果图  效果如下: 接着上代码: <script type="text/javascript"> /** * Copyright (c) 2016 hustcc * License: MIT * Version: v1.0.1 *

Django 编写博客网站的用户管理部分(采用自有的 django.contrib.auth) 2. 登陆登出和用户信息管理

续前Django 编写博客网站的用户管理部分(采用自有的 django.contrib.auth) 1. 注册部分 项目工具:Python 2.7.11  Django 1.10.2  Bootstrap 3.3.0   IDE:eclipse Pydev 1. 由于Django自带auth, 故仅需编写登录登出的url和template即可 urls常见上篇 template代码如下仅供参考: login 1 {% extends "account_base.html" %} 2 3

个人博客主页搭建随笔

经常在各种论坛.博客还有 github 上活跃的朋友不难发现,许多大牛都有自己的网站,也多以博客为主.博主作为一个立志前端的大白,难道不应该和大牛学习么? 说干就干,前端部分和 web 开发博主做了很多学习和总结,不少也写成了博客.对于后端,博主不敢说完全没有经验,但接触的也都比较简单.于是乎,博主去年六月底开始看 Node 和 Express,利用空闲时间做了自己的博客,现阶段还有许多不足,需要后续不断改进.不过这不妨碍博主先总结一下自己的感受. UI设计 和 架构设计 博主深刻的感受到自己并

Linux系统编程博客参考

通过看前人的博客更易于把握知识要点 http://www.cnblogs.com/mickole/category/496206.html <Linux系统编程> http://www.cnblogs.com/DayByDay/category/599079.html <UNIX环境高级编程学习笔记> http://blog.csdn.net/bytxl/article/details/8584993 UNIX环境高级编程(第2版)- 第1-10章

博客美化基本后台设置与样式设置

1. 首先向管理员申请开通js权限 2.点击管理,选择选项,在控件显示设置选中公告 3.然后点击 管理-->设置-- 在“博客侧边栏公告(支持HTML代码)”下面贴上html代码就ok了 (1).偷食小老鼠 代码如下: <object type="application/x-shockwave-flash" style="outline:none;" data="http://cdn.abowman.com/widgets/hamster/ha

Django从零搭建个人博客 | 使用allauth插件管理用户登录与注册

原文博客地址:http://www.eosones.com/ django-allauth是最受欢迎的管理用户登录与注册的第三方Django安装包,可以大大简化我们用户注册,登录及账户管理,其核心功能包括用户注册.忘记密码.登录(微信,微博等第三方登录:邮箱验证).登录后密码重置.邮箱发送密码重置链接.退出等. 安装与设置 运行CMD,打开虚拟环境 pip install django-allauth 安装好后设置Myblog / settings.py,将allauth相关APP加入到INST

用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级

目录 目录 前文列表 扩展阅读 Alembic 查看指令 manager db 的可用选项 初始化 DB Migrate 开始第一次跟踪 将记录文件应用到数据库中实时升级数据库结构 回滚到某一个记录环境中 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 Flask 来写个轻博客 (3) - (M)VC_连接 MySQL 和 SQLAlchemy 用 Flask 来写个轻博客 (4) - (M)VC_创建数据模型