报障系统之博客主页及后台管理
分类:
IT文章
•
2022-04-30 19:12:28
个人博客:
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