引言
开发以下功能需要掌握技能:
1. 程序设计
2.Python
3.Python Django框架
4. Bootstrap前端框架
5. Mysql
6. Redis
7. Centos Linux 服务器部署:Centos、Nginx、uWSGI、Supervisord、Redis、Mysql
网站概览
1.首页
2.资讯
3. 关于我们
4. 网站管理后台登陆界面
5.网站管理后台主功能模块界面
Bootstrap移动端展示效果图
1.首页
2.案例
3.管理后台图表统计
程序目录结构
目录结构:
程序主要公共开发模块讲解
1. 富文本编辑器
管理后台前端表现
公共模块插件方法
# -*- coding: utf-8 -*-
from__future__importunicode_literals
fromdjango.shortcutsimportrender
fromdjango.httpimportHttpResponse
fromdjango.confimportsettings
fromdjango.views.decorators.csrfimportcsrf_exempt
importos
importuuid
importjson
importdatetimeasdt
fromkindeditor.modelsimportKindEditor
# Create your views here.
defuptest(request):
ifrequest.method =="GET":
returnrender(request,'test.html')
ifrequest.method =="POST":
title = request.POST.get('title','')
content = request.POST.get('content','')
KindEditor(title=title,content=content).save()
returnrender(request,'kindeditor.html')
deftestviews(request):
ifrequest.method =="GET":
data = KindEditor.objects.all()[]
ret = {"data":data}
returnrender(request,'testviews.html',{"ret":ret})
@csrf_exempt
defupload_image(request,dir_name):
##################
# kindeditor图片上传返回数据格式说明:
# {"error": 1, "message": "出错信息"}
# {"error": 0, "url": "图片地址"}
##################
result = {"error":1,"message":"上传出错"}
files = request.FILES.get("imgFile",None)
iffiles:
result =image_upload(files,dir_name)
returnHttpResponse(json.dumps(result),content_type="application/json")
#目录创建
defupload_generation_dir(dir_name):
today = dt.datetime.today()
dir_name = dir_name +'/%d/%d/'%(today.year,today.month)
if notos.path.exists(settings.MEDIA_ROOT):
os.makedirs(settings.MEDIA_ROOT)
returndir_name
# 图片上传
defimage_upload(files,dir_name):
#允许上传文件类型
allow_suffix =['jpg','png','jpeg','gif','bmp']
file_suffix = files.name.split(".")[-1]
iffile_suffixnot inallow_suffix:
return{"error":1,"message":"图片格式不正确"}
relative_path_file = upload_generation_dir(dir_name)
path=os.path.join(settings.MEDIA_ROOT,relative_path_file)
printpath
if notos.path.exists(path):#如果目录不存在创建目录
os.makedirs(path)
file_name=str(uuid.uuid1())+"."+file_suffix
path_file=os.path.join(path,file_name)
file_url = settings.MEDIA_URL + relative_path_file + file_name
open(path_file,'wb').write(files.file.read())
return{"error":,"url": file_url}
Django服务端代码
# 新闻管理
@auth
defadminnews(request,page):
ifrequest.method =='GET':
start,end,page = PageSEP(page)
pagecount = models.News.objects.all().count()
data = models.News.objects.all().order_by('-id')[start:end]
ret = {"data":data,"page":PageNum(page,pagecount,"admins/news")}
queryid = request.GET.get('queryid')
ifqueryid:
querydata = models.News.objects.filter(id=queryid)
ifquerydata:
querydata = querydata.values("content")[].get("content")
returnHttpResponse(json.dumps({"success": querydata}))
else:
returnHttpResponse(json.dumps({"success":"查无数据"}))
returnrender(request,'ADnews.html',{"ret":ret})
ifrequest.method =='POST':
# 新增
title = request.POST.get('title')
iftitle:
content = request.POST.get('content')
author = request.POST.get('author')
uptime = request.POST.get('uptime')
models.News(title=title,content=content,author=author,uptime=uptime).save()
# 删除
delid = request.POST.get('delid')
ifdelid:
models.News.objects.filter(id=delid).delete()
# 修改
uptitle = request.POST.get('uptitle')
ifuptitle:
upid = request.POST.get("upid")
upcontent = request.POST.get('upcontent')
upauthor = request.POST.get('upauthor')
upuptime = request.POST.get('upuptime')
models.News.objects.filter(id=upid).update(title=uptitle,content=upcontent,author=upauthor,uptime=upuptime)
# 搜索用户
search = request.POST.get('search')
ifsearch:
searchid = request.POST.get('searchid')
searchtitle = request.POST.get('searchtitle')
ifsearchtitle:
data = models.News.objects.filter(title__icontains=searchtitle)
ret = {'data': data}
returnrender(request,'ADnews.html',{'ret': ret})
ifsearchid:
data = models.News.objects.filter(id=searchid)
ret = {'data': data}
returnrender(request,'ADnews.html',{'ret': ret})
returnHttpResponseRedirect('/admins/news')
returnHttpResponseRedirect('/admins/news')
2.网站验证码
前端表现
公共模块插件方法
# -*- coding:utf-8 -*-
fromPILimportImage,ImageDraw,ImageFont,ImageFilter
importrandom,time
# img 存储过程
defSaveImg(upimg):
photoname ='static/upload/%s.%s'% (str(time.time()).split('.')[],str(upimg).decode('utf-8').split('.')[-1])
img = Image.open(upimg)
img.save(photoname)
img ='/'+ photoname
returnimg
classPicture(object):
def__init__(self,text_str,size,background):
'''
text_str: 验证码显示的字符组成的字符串
size: 图片大小
background: 背景颜色
'''
self.text_list =list(text_str)
self.size = size
self.background = background
defcreate_pic(self):
'''
创建一张图片
'''
self.width,self.height =self.size
self.img = Image.new("RGB",self.size,self.background)
# 实例化画笔
self.draw = ImageDraw.Draw(self.img)
defcreate_point(self,num,color):
'''
num: 画点的数量
color: 点的颜色
功能:画点
'''
foriinrange(num):
self.draw.point(
(random.randint(,self.width),random.randint(,self.height)),
fill=color
)
defcreate_line(self,num,color):
'''
num: 线条的数量
color: 线条的颜色
功能:画线条
'''
foriinrange(num):
self.draw.line(
[
(random.randint(,self.width),random.randint(,self.height)),
(random.randint(,self.width),random.randint(,self.height))
],
fill=color
)
defcreate_text(self,font_type,font_size,font_color,font_num,start_xy):
'''
font_type: 字体
font_size: 文字大小
font_color: 文字颜色
font_num: 文字数量
start_xy: 第一个字左上角坐标,元组类型,如 (5,5)
功能: 画文字
'''
font = ImageFont.truetype(font_type,font_size)
self.strs = random.sample(self.text_list,font_num)
self.draw.text(start_xy," ".join(self.strs),font=font,fill=font_color)
defopera(self):
'''
功能:给画出来的线条,文字,扭曲一下,缩放一下,位移一下,滤镜一下。
就是让它看起来有点歪,有点扭。
'''
params = [
1-float(random.randint(1,2)) /100,
,
,
,
1-float(random.randint(1,10)) /100,
float(random.randint(1,2)) /500,
0.001,
float(random.randint(1,2)) /500
]
self.img =self.img.transform(self.size,Image.PERSPECTIVE,params)
self.img =self.img.filter(ImageFilter.EDGE_ENHANCE_MORE)
# if __name__ == "__main__":
defccode():
strings ="abcdefghjkmnpqrstwxyz23456789ABCDEFGHJKLMNPQRSTWXYZ"
size = (150,50)
background ='white'
pic = Picture(strings,size,background)
pic.create_pic()
pic.create_point(500,(220,220,220))
pic.create_line(30,(220,220,220))
pic.create_text("simsun.ttc",24,(,,205),5,(7,7))
pic.opera()
# pic.img.show()
img,strs=pic.img,''.join(pic.strs)
returnimg,strs
Django服务端代码
# 验证码
defvalidate(request):
img,strs = ccode()
mstream = StringIO.StringIO()
img.save(mstream,"GIF")
request.session['validate'] = strs
returnHttpResponse(mstream.getvalue(),"image/gif")
Django服务端判断验证码是否输入正确代码
# 首页登陆
defadminlogin(request):
ifrequest.method =='GET':
request.session.clear()
returnrender(request,'ADlogin.html')
ifrequest.method =='POST':
username = request.POST.get('username','')
password = request.POST.get('password','')
code = request.POST.get('ccode','')
ifcode.lower() != request.session.get('validate','error').lower():
returnHttpResponse(json.dumps({"error":'验证码错误,请重新输入!'}))
3. 网站权限管理
程序设计逻辑略过
代码部分略过
请自行思考
前端程序表现1
前端程序表现2
前端程序表现3
前端程序表现4
4. 网站留言管理
前端表现
Django服务器代码
代码略过,捕获新增留言条数,查看后状态清空为0
5. 数据统计模块
PS:打点数据统计用户行为由服务器完成,前端未主动发起请求
前端表现
Django服务器端
5.1. 捕获用户访问页面次数,捕获用户访问IP
# 统计用户信息
defcollectinfo(request):
ifrequest.META.has_key('HTTP_X_FORWARDED_FOR'):
ip = request.META['HTTP_X_FORWARDED_FOR']
else:
ip = request.META['REMOTE_ADDR']
path = request.path
if"news"inpath:
path ="/news"
CollectInfo(ip=ip,path=path).save()
5.2. 分析筛选数据并返回给前端
# 图表统计
@auth
defadminchartdata(request):
starttime = request.GET.get("starttime")
endtime = request.GET.get("endtime")
if notstarttimeand notendtime:
endtime = datetime.now()
starttime = endtime - timedelta(days=7)
endtime =str(endtime)[:16]
starttime =str(starttime)[:16]
path = CollectInfo.objects.filter(createtime__range=(starttime,endtime)).values("path").distinct()
pathlist = []
pathdata = []
iplist = []
foriinpath:
ifi.get("path")=="/":
pathlist.append("首页")
ifi.get("path")=="/information":
pathlist.append("资讯")
ifi.get("path")=="/case":
pathlist.append("案例")
ifi.get("path")=="/about":
pathlist.append("关于")
ifi.get("path")=="/news":
pathlist.append("新闻")
data = CollectInfo.objects.filter(createtime__range=(starttime,endtime),path=i.get("path"))
pathdata.append(data.count())
iplist.append(data.values("ip").distinct().count())
pathlist = json.dumps(pathlist,encoding="UTF-8",ensure_ascii=False)
ret = {"pathlist":pathlist,"pathdata":pathdata,"iplist":iplist,"starttime":starttime,"endtime":endtime}
returnrender(request,'ADchartdata.html',ret)
Bootstrap框架 + Echarts插件+jedate日期选择插件
图表分析前端代码略过
6. 装饰函数,判断登陆是否失效验证
备注:Java Web开发框架中专业称呼:Filter、过滤器、拦截器,由单独配置文件或方法处理。
判断cookie中的信息
# 判断登陆
defauth(func):
definner(request,*args,**kwargs):
adminname = request.session.get('admin','error')
# admin用户拥有最高权限
ifadminname =="admin":
returnfunc(request,*args,**kwargs)
username = models.UserManage.objects.filter(username= adminname)
ifusername:
ifroles = ifrole(request,adminname)
ififroles:
returnHttpResponse(ifroles)
else:
returnfunc(request,*args,**kwargs)
else:
returnHttpResponseRedirect('/admins')
returninner
登陆操作设置cookie中的seesion信息用于服务端判定登陆信息
# 首页登陆
defadminlogin(request):
ifrequest.method =='GET':
request.session.clear()
returnrender(request,'ADlogin.html')
ifrequest.method =='POST':
username = request.POST.get('username','')
password = request.POST.get('password','')
code = request.POST.get('ccode','')
ifcode.lower() != request.session.get('validate','error').lower():
returnHttpResponse(json.dumps({"error":'验证码错误,请重新输入!'}))
user = models.UserManage.objects.filter(username__exact= username,password__exact= password)
ifuser:
userstatus = models.UserManage.objects.filter(username__exact= username,status=1)
ifuserstatus:
request.session['admin'] = username
returnHttpResponse(json.dumps({"success":'登陆成功!'}))
else:
returnHttpResponse(json.dumps({"error":'账号未激活,请激活!'}))
else:
returnHttpResponse(json.dumps({"error":'用户名或密码错误,请重录!'}))
退出登陆
后台每个接口操作前判断
# 首页
@auth
defadminmanage(request):
username = request.session.get('admin','error')
rolename = models.UserManage.objects.filter(username= username).values("DoManage__username")[].get("DoManage__username")
MessageNum =int(MessageManage.objects.all().count())-int(models.MessageNum.objects.filter(id=1).values("MessageNum")[].get("MessageNum"))
returnrender(request,'ADindex.html',{'username':username,"rolename": rolename,"MessageNum":MessageNum})
7. 其他公共方法
7.1 增
7.2 删
7.3 改
7.4 模板数据封装绑定
7.5 JSON数据封装、Ajax操作、分页操作
7.6 Redis Nosql常用数据高速缓存查询
8. Redis存储中文字符编码问题
解决JSON中文字符存储编码问题
defmoviedata():
data = models.IndexMovieInfo.objects.all()
list = []
foriindata:
a = {str("id"):str(i.id),str("img"):str(i.img),str("a"):str(i.a),str("title"):str(i.title.encode("utf-8"))}
list.append(a)
r.set("movie",json.dumps(list,encoding="UTF-8",ensure_ascii=False))
每分钟多线程更新Redis缓存数据
defwhiletask():
while True:
time.sleep(60)
moviedata()
bannerdata()
informationdata()
informationhotdata()
caseinfo()
defTimedTask():
t = threading.Thread(target=whiletask,args=())
t.setDaemon(True)
t.start()
9. 单张图片存储公共方法、
公共方法
# img 存储过程
defSaveImg(upimg):
photoname ='static/upload/%s.%s'% (str(time.time()).split('.')[],str(upimg).decode('utf-8').split('.')[-1])
img = Image.open(upimg)
img.save(photoname)
img ='/'+ photoname
returnimg
单张图片修改存储
# 修改Banner信息
upid = request.POST.get('upid')
ifupid:
uplink = request.POST.get('uplink')
uptitle = request.POST.get('uptitle')
upcontent = request.POST.get('upcontent')
upstatus = request.POST.get('upstatus')
try:
upimg = request.FILES['upimg']
except:
upimg =None
ifupimg:
img = SaveImg(upimg)
models.IndexBanerInfo.objects.filter(id=upid).update(img=img,a=uplink,title=uptitle,p=upcontent,status=upstatus)
models.IndexBanerInfo.objects.filter(id=upid).update(a=uplink,title=uptitle,p=upcontent,status=upstatus)
returnHttpResponseRedirect('/admins/banner')
10. CSV数据导出操作公共函数
前端表现
导出结果表现
公共函数方法
# csv 操作
importcsv
fromdjango.httpimportHttpResponse
defcopycsv(data):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] ='attachment; filename="order-export.csv"'
# csvfile = open('order-export.csv', 'wb')
# writer = csv.writer(csvfile)
writer = csv.writer(response)
writer.writerow(['ID'.decode('utf-8').encode('GB2312'),'用户名'.decode('utf-8').encode('GB2312'),'电话'.decode('utf-8').encode('GB2312'),'邮箱'.decode('utf-8').encode('GB2312'),'留言内容'.decode('utf-8').encode('GB2312'),'时间'.decode('utf-8').encode('GB2312')])
# data = [ (),()]
writer.writerows(data)
# csvfile.close()
returnresponse
Django服务端数据导出操作
# 留言管理
@auth
defadminmessage(request,page):
ifrequest.method =="GET":
docsv = request.GET.get("docsv")
ifdocsv:
quessydata = MessageManage.objects.all()
data = []
forrowinquessydata:
query = [row.id,(row.name).encode('GB2312'),(row.phone).encode('GB2312'),(row.email).encode('GB2312'),(row.content).encode('GB2312'),str(str(row.createtime)[:-6])]
data.append(query)
returncopycsv(data)
12. 涉及内容太多无法再此一一讲解
以上模块仅作参考使用,教程到此结束,其他的请自行阅读代码
Github地址:https://github.com/Github-Benjamin/HomePage
网站用户前端页面参考:北风网瓢城Web俱乐部李彦辉Bootstrap教程,在此表示由衷感谢!
赠言
以下图片收藏于2012年百度暴风影音,截图设备为:Moto Defy +
领取专属 10元无门槛券
私享最新 技术干货