简明Python开发教程(6):用Django搭建网站

前面已经分享了Python的基础知识和典型应用,那么如何可视化呈现结果并进行交互?
一般用网页形式进行展示,网页展示结果、交互,服务器后台提供数据支持。开发网站又是一个复杂的工作。
幸好Python的Django框架可以让我们非常容易的搭建网站系统,只需要我们学习一点点HTML、CSS、JavaScript等前端知识,了解一下Django的工作原理就可以工作了。
前期我们梳理了工作岗位需要掌握的11大类、327小类技能点,并对27位同事的技能掌握进行摸底调查,分为:没听过、初级、中级、高级四部分;
同时统计近5年的外出培训记录。
目前需要开发一个网站,提供查询功能:
1)按人员查:对比显示该同事的技能掌握情况和培训记录;
2)按技能查询:显示不同基本人员分布情况

1 Django介绍

Django是用Python开发的免费开源web框架。
当初我使用自强学堂完成学习入门,推荐。
首先需要安装相应版本的Django,如1.11。
如果已经安装Anaconda,那么使用conda intsall django。即可完成安装。
一般情况,开发Django应用有以下几步:

1.1 创建一个工程

使用django-admin.py startproject project_name创建一个新工程,然后发现会自动新建一个文件夹,有着一定的模板。

简明Python开发教程(6):用Django搭建网站_第1张图片
image.png

可以看到目录结构基本如下:

hrinfo/
    manage.py
    hrifno/
        __init__.py
        settings.py
        urls.py
        wsgi.py

urls.py写一些url解析规则,setting.py包含一些全局配置信息,manage.py提供一些管理功能。
如进入工程目录,运行开发环境,测试Django是否工作正常。

简明Python开发教程(6):用Django搭建网站_第2张图片
image.png

一切正常,打开浏览器,输入127.0.0.1:8000,结果如下,说明Django工作正常。

简明Python开发教程(6):用Django搭建网站_第3张图片
image.png

1.2 新建一个应用App

进入工程目录后,输入python manage.py startapp hrskill,可以发现新建一个hrskill文件夹,包含若干文件:

简明Python开发教程(6):用Django搭建网站_第4张图片
image.png

这里最重要的是views.py文件,写网站后台处理逻辑。

1.3 修改配置setting.py文件

打开setting.py文件,增加App名称,如果希望关联数据库,如修改为Mysql
数据库,也可以配置,这里简化处理,这里不配数据库。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hrskill',  #新增配置
]

1.4 测试应用功能

通过修改urls.py 和 views.py来测试应用是否正常工作。比如我们想访问127.0.0.1:8000时,能够显示欢迎语句。
在views.py新增index函数:

from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
def index(request):
    return HttpResponse(u"欢迎光临!")

index()返回 HttpResponse 对象,可以显示在网页上,现在需要规定那个网址能使用这个函数,也就是需要在urls.py进行修改:

from django.conf.urls import url
from django.contrib import admin

from hrskill import views as hrskill_views #新增

urlpatterns = [
    url(r'^$', hrskill_views.index),  #新增url解析规则,什么网址对应什么函数
    url(r'^admin/', admin.site.urls),
]

其中网址写法符合正则表达式规则。
然后运行开发服务器 python manage.py runserver,打开浏览器,输入127.0.0.1:8000,结果如下:

简明Python开发教程(6):用Django搭建网站_第5张图片
image.png

1.5 使用模板(templates)进行交互

前面通过HttpResponse 来把内容显示到网页上,非常简单,能做的事也很少。
更多的我们是用模板templates的方法,就是事先写好html文件,然后直接返回这个html文件,这样就可以美化页面。
在hrskill文件夹下新建templates文件夹,然后新建一个index.html文件。
/templates/index.html内容如下:



    
        
        欢迎使用
    
    
        欢迎跟着朱老师学Django.
    

然后修改/hrskill/views.py如下:

from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse  #可以注释掉
def index(request):
    return render(request, 'index.html')  #修改为这样即可
    #return HttpResponse(u"欢迎光临!")

然后可以刷新下网页(由于之前开发服务器一直运行,修改views.py会自动生效,无需重启,非常方便开发调式),结果已经更新。完美。


简明Python开发教程(6):用Django搭建网站_第6张图片
image.png

1.6 对模板进行渲染

上面功能还是很单一,只能返回写好的html文件。服务器更强大的应该是动态更新html文件,可以交互,比如不同用户访问,通过后台查询账号对应用户姓名,显示个性化欢迎语。
修改/templates/index.html内容如下:



    
        
        欢迎使用
    
    
        {{name}},欢迎跟着朱老师学Django.
    

修改/hrskill/views.py如下:

from django.shortcuts import render
def index(request):
    name = '朱锋'  #模拟获取后台获取用户姓名,这里省略
    return render(request, 'index.html',{'name':name})  #注意传name参数给前端

刷新网页,效果如下:

简明Python开发教程(6):用Django搭建网站_第7张图片
image.png

1.7 前端传参数给后台

很多时候,用户需要在前端网页输入某些关键字,然后传递给后台,后台根据这些参数进行处理,并返回结果。
这里简单模拟下用户在前端网页输入数字后,后台获取数字后加10返回,显示。
首先修改/templates/index.html内容如下:



    
        
        欢迎使用
        
    
    
        

欢迎跟着朱老师学Django.

由于使用Jquery,需要导入,将相应js文件放入/hrskill/static/js目录下(自己新建)。
同时上面html文件中增加了一个表单form及对应的动作,包括一个输入框input,一个提交按钮,通过JavaScript的Ajax技术获取后台数据,获取数据后修改p1内容。
此时刷新网页,效果如下:

简明Python开发教程(6):用Django搭建网站_第8张图片
image.png

此时点击Go应该没有任何反应,因为后台没进行后台修改。
接下来我们要修改后台处理逻辑。
首先增加一个url网址对应的views函数。
修改/hringo/urls.py如下:

from django.conf.urls import url
from django.contrib import admin
from hrskill import views as hrskill_views #新增
urlpatterns = [
    url(r'^$', hrskill_views.index),  #新增url解析规则,什么网址对应什么函数
    url(r'^search/$', hrskill_views.search),  #新增search Url对应view中函数
    url(r'^admin/', admin.site.urls),
]

此时点击Go,Django后台会报错,因为没有修改views.py。
修改/hrskill/views.py如下:

from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
import json  #新增json处理  
def index(request):
    name = '朱锋'  #模拟获取后台获取用户姓名,这里省略
    return render(request, 'index.html',{'name':name})  #修改为这样即可
def search(request): #新增search函数
    name = request.GET['name']
    ret = {}
    ret['data'] = '你输入的字符串是——{}'.format(name)
    return HttpResponse(json.dumps(ret),content_type='application/json')

现在我们在输入框输入任何字符串,点击“Go”,提交后看看效果。(如果没响应,建议重启开发服务器再试试)。
输入“今天天气真好”,然后点击Go,效果如下:

简明Python开发教程(6):用Django搭建网站_第9张图片
点击前.png

简明Python开发教程(6):用Django搭建网站_第10张图片
点击后.png

偶尔可能犯迷糊,参数传递有问题,重新加载正常,需要前端大牛帮忙解决


以上,我们已经简单介绍了Django,包括网页的基本交互,接下来就是丰富处理逻辑,美化前端页面,都在上面的框架内完成。

2 前端优化——AdminLTE、Bootstrap、Echarts

为了使前端页面更美观,也使得交互更近优化,我们可以学习一些基本的前端技术的使用,如:
Bootstrap简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。
AdminLTE,是基于Bootstrap3高度可定制的响应式管理模板,是网页更简单。
Echarts开源免费的可视化图表。
上述工具,自己查看教程学习,下载相应的js文件,放置合适路径。因为我也只是会用

3 最终实现

回到一开始的项目需求,按人员或技能查询并用合适图表对比显示分析。
首先看看后台Mysql两个数据库结构:
staff_skill表格式,提供人员技能掌握情况。

image.png

training_record表样例,提供人员培训记录。

image.png

3.1 HTML文件设计

总共设计3个html页面,分别是首页index.html、人员查询页面searchstaff.html和技能查询页面searchskill.html。
下载相应的js、css文件,放到/hrskill/static/下合适路径。
index.html如下(说实话,可能有些css、js文件是不必要,但是我不知道):



    
        
        欢迎使用
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    
        
    

人员查询searchstaff.html文件如下:



    
        
        人员查询
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    
        

        
    

通过输入被查询人员姓名,查询显示其技能和培训情况。
技能查询searchsskill.html文件如下:

未完待续,大家可以完成

通过输入被查询技能名称,查询显示人员掌握情况。

3.2 后台处理逻辑设置

修改urls.py如下:

from django.conf.urls import url
from django.contrib import admin
from hrskill import views as hrskill_views #新增
urlpatterns = [
    url(r'^$', hrskill_views.index),  #新增url解析规则,什么网址对应什么函数
    url(r'^searchstaff/$', hrskill_views.searchstaff),  #新增searchstaff函数
    url(r'^searchskill/$', hrskill_views.searchskill),  #新增searchskill函数
    url(r'^admin/', admin.site.urls),
]

修改views.py如下:

from django.shortcuts import render
from django.http import HttpResponse
import pandas as pd
import json  #新增json处理  
import pymysql #操作数据库
ip = '127.0.0.1'
user = 'root'
password = 'root'
db = 'hrinfo'
def index(request):
    name = '朱锋'  #模拟获取后台获取用户姓名,这里省略
    return render(request, 'index.html',{'name':name})  #修改为这样即可
def staffinfo(request):    
    return render(request, 'searchstaff.html')  
def skillinfo(request):
    return render(request, 'searchskill.html')  
#查询人员信息
def getstaff(request): 
    name = request.GET["username"]
    conn = pymysql.connect(host=ip, port=3306, user=user, passwd=password, db=db,charset='utf8')
    sql_skill = "SELECT * FROM staff_skill"
    skills = pd.read_sql(sql_skill,conn)
    skills = skills[skills['name']==name]
    ret = {}
    cols = []
    col = ['name','skill_name','date','no','primary','middle','senior']
    col_title = ['姓名','技能名称','认证日期','没听过','初级','中级','高级']
    for i in range(len(col)):
        col_f = {}       
        col_f['field'] = col[i]
        col_f['title'] = col_title[i]
        cols.append(col_f)
    ret['cols'] = cols
    a_skills = []
    for a_skill,group in skills.groupby(['a_skill']):
        row = {}
        date = max(group['skill_date'])
        num = len(group)
        no = len(group[group['skill_level']=='没听过'])
        primary = len(group[group['skill_level']=='初级'])
        middle = len(group[group['skill_level']=='中级'])
        senior = len(group[group['skill_level']=='高级'])
        row['name'] = name
        row['skill_name'] = a_skill
        row['date'] = date
        row['no'] = '{}/{}'.format(no,num)
        row['primary'] = '{}/{}'.format(primary,num)
        row['middle'] = '{}/{}'.format(middle,num)
        row['senior'] = '{}/{}'.format(senior,num)
        b_skills = []
        for b_skill ,b_group in group.groupby(['b_skill']):
            b_row = {}
            b_row['name'] = name
            b_row['skill_name'] = b_skill
            b_row['date'] = date
            num = len(b_group)
            no = len(b_group[b_group['skill_level']=='没听过'])
            primary = len(b_group[b_group['skill_level']=='初级'])
            middle = len(b_group[b_group['skill_level']=='中级'])
            senior = len(b_group[b_group['skill_level']=='高级'])
            b_row['no'] = '{}/{}'.format(no,num)
            b_row['primary'] = '{}/{}'.format(primary,num)
            b_row['middle'] = '{}/{}'.format(middle,num)
            b_row['senior'] = '{}/{}'.format(senior,num)
            b_skills.append(b_row)
        row['b_skills'] = b_skills
        a_skills.append(row)    
    ret['a_skills'] = a_skills
    
    sql_train = "SELECT * FROM training_record"
    trains = pd.read_sql(sql_train,conn)
    cj_trains = trains[trains['name']==name]
    zj_trains = pd.DataFrame()
    for i in trains.index:
        speaker = trains.loc[i]['speaker']
        if name in speaker:
            zj_trains = zj_trains.append(trains.loc[i],ignore_index=True)
    re_train = []
    if not zj_trains.empty:
        for topic in set(zj_trains['train_topic']):    
            topic_train = zj_trains[zj_trains['train_topic'] == topic][['train_date','days','train_class','train_loc']]
            topic_train = topic_train.drop_duplicates()
            row = dict(topic_train.iloc[0])
            row['name'] = name
            row['topic'] = topic
            row['isspeaker'] = '是'
            re_train.append(row)
    if not cj_trains.empty:
        for i in cj_trains.index:
            topic = cj_trains.loc[i]['train_topic']
            if zj_trains.empty or (topic not in set(zj_trains['train_topic'])):
                row = dict(cj_trains.loc[i][['train_date','days','train_class','train_loc']])
                row['name'] = name
                row['topic'] = topic
                row['isspeaker'] = '否'
                re_train.append(row)
    ret['train_record'] = re_train
    cols_train = []
    col_train = ['name','topic','train_date','days','train_class','train_loc','isspeaker']
    col_title_train = ['姓名','培训名称','培训日期','培训天数','培训类型','培训地点','是否为讲师']
    for i in range(len(col_train)):
        col_f = {}       
        col_f['field'] = col_train[i]
        col_f['title'] = col_title_train[i]
        cols_train.append(col_f)
    ret['cols_train'] = cols_train
    
    #写评语
    num = len(skills)
    senior = len(skills[skills['skill_level']=='高级'])
    middle = len((skills[skills['skill_level']=='中级']))
    primary = len((skills[skills['skill_level']=='初级']))
    no = len((skills[skills['skill_level']=='没听过']))
    num_zj = len(zj_trains)
    num_cj = len(zj_trains) + len(cj_trains)
    remark = "
{}同学,在全部的{}个知识点中,掌握情况大概如下:高级{}/{},中级{}/{},初级{}/{},没听过{}/{}。\ 近期主讲{}次培训,参加{}次培训。
".format(name,num,senior,num,middle,num,primary,num,no,num,num_zj,num_cj) ret['remark'] = remark return HttpResponse(json.dumps(ret),content_type='application/json')

由于时间关系,后台处理逻辑实现比较乱,建议单独一个模块,写各种函数,实现数据处理功能。
现在我们可以看看网页的效果
点击左侧“人员查询”:

简明Python开发教程(6):用Django搭建网站_第11张图片
image.png

输入姓名“XX”,点击查询:

简明Python开发教程(6):用Django搭建网站_第12张图片
image.png

由于时间关系,技能查询功能未实现,同时显示方式、评价都有很多优化的地方,使得交互更加友好。
期待你们的完善。
全部教程到此结束,砖已抛出,期待你们的玉。
Python真是零基础编程的神器!

你可能感兴趣的:(简明Python开发教程(6):用Django搭建网站)