Python Django框架 Web网站管理系统开发

引言

开发以下功能需要掌握技能:

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 +

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180613G0251600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券