Django员工管理系统(ems)
- 需求分析:
1.实现管理员的注册、登陆页面
注册:用户名、真实名字、密码、确认密码、性别、验证码
用户名需要判断是否合法、是否存在,loading图片提示
密码和确认密码是否相同,loading图片提示
验证码是否正确,loading图片提示
点击提交时:判断信息是否正确,如错误弹窗提示,如正确,重定向到登陆页面
登陆:用户名、密码、选框(记住我7天)
点击提交时:判断该用户名密码是否正确,如错误弹窗提示,如正确,重定向到主页面
2.实现查看、增加、删除、修改员工信息页面
查看:
分页显示员工数据,下方有 上一页,页码,下一页,如没有则相应不显示
点击则跳转到相应页面
每条员工数据后有删除、修改 a标签,下方有增加员工信息按钮
点删除,提示是否删除框,点修改,则跳转到修改页面,点增加,跳转到增加页面
增加:头像、员工名、年龄、薪水,提交按钮
点提交,信息添加到最后一个,并跳转到查看页面的最后一页
删除:判断是否删除,如是,则删除,跳转到原查看页面
注:如删除的员工为最后一个,则跳转到最后一页
修改:自动获取要修改员工的信息,提交按钮
提交后跳转到原查看页面
注:以上页面都需要判断是否登陆成功,如果未登录,则强制登陆(跳转到登陆页面)
- 前期准备
建立虚拟环境:
python3.5、django2.0.6、mysql5.5.6、pip(下载第三方库的工具)、
virtualenv(虚拟环境)、virtualenvwrapper(虚拟环境管理工具)、mysqlclient(Django连接数据库的第三方库)、pillow(验证码第三方包)
IDE:pycharm
navicat: 查看数据库(也可没有)
- 创建Django项目(项目名 ems2_project)
1.创建两个APP:user、emp
python manage.py startapp user
python manage.py startapp emp
# user:管理员注册登陆
# emp:员工的增删查改
2.项目setting里相关配置
挂载app
设置数据库为mysql,并添加相应配置
设置session存活日期:
# SESSION_EXPIRE_AT_BROWSER_CLOSE = True
增加管理者头像图片所需的文件位置:
/static (在项目根目录下创建:所有的静态资料都放在下面)
把存放图片的文件添加到静态资源查找位置
# STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
3.项目urls里相关配置
导入app里的urls (每个app下创建自己的urls.py文件)
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include("user.urls")),
path('emp/', include("emp.urls")),
]
注:每个app里功能对应的url应放在app里
4.user相关功能实现
model操作:
创建User类并创建相应的属性、类型
class User(models.Model):
username = models.CharField(max_length=20)
name = models.CharField(max_length=20)
passwd = models.CharField(max_length=20)
sex = models.CharField(max_length=10)
创建完毕后,执行迁移命令,生成对应数据表
python manage.py makemigratons
python manage.py migrate
urls操作:
先创建urls.py文件
加入 app_name='user' :创建app命名空间,建立软连接
再创建相应url地址:
urlpatterns = [
path('login/', views.login, name = 'login'),
path('loginlogic/', views.loginlogic, name = 'loginlogic'),
path('regist/', views.regist, name = 'regist'),
path('registlogic/', views.registlogic, name = 'registlogic'),
path('checkname/', views.checkname, name = 'checkname'),
path('checknumber/', views.checknumber, name = 'checknumber'),
path('getcaptcha/', views.getcaptcha, name = 'getcaptcha'),
]
注:name为各url命名空间
view操作:(创建视图函数)
注:创建相应的htnl页面
注册:
def regist(request):
return render(request, "user/regist.html")
注册相应判断:
def registlogic(request):
# 获取相应参数属性
username = request.POST.get("username")
name = request.POST.get("name")
pwd = request.POST.get("pwd")
repwd = request.POST.get("repwd")
sex = request.POST.get("sex")
number = request.POST.get("number")
code = request.session.get("code")
# 用户名、密码、验证码判断
if code.lower() == number.lower():
res = User.objects.filter(username=username)
if not res and name and pwd == repwd:
User.objects.create(username=username, name=name, passwd=pwd, sex=sex)
return HttpResponse("1")
return HttpResponse("0")
注册中输入用户名之后判断:
def checkname(request): ...
注册中输入验证码之后判断:
def checknumber(request): ...
注册中的验证码显示:
def getcaptcha(request):
image = ImageCaptcha()
code = random.sample(string.ascii_lowercase+string.ascii_uppercase+string.digits,5)
random_code = ''.join(code)
request.session['code'] = random_code
data = image.generate(random_code)
return HttpResponse(data, "image/png")
注:需要验证码相关文件 captcha
登陆:
def login(request):
# 先判断是否有cookie值 中文需要解码
username = request.COOKIES.get("username")
if username:
username = username.encode('latin-1').decode('utf-8')
pwd = request.COOKIES.get("pwd")
message = User.objects.filter(username=username, passwd=pwd)
# 如cookie值正确,直接进入主页面
if message:
request.session['life'] = True
return redirect("emp:empList")
# 没有或错误的cookie,进入登陆页面
return render(request, "user/login.html")
登陆相应判断:
def loginlogic(request):
# 获取用户名,密码 用户名需编码
username = request.POST.get("username")
pwd = request.POST.get("pwd")
# 判断信息是否正确
message = User.objects.filter(username=username, passwd=pwd)
if username:
username = username.encode('utf-8').decode('latin-1')
# 如正确,则判断是否记住密码,是否设置cookie
if message:
res = HttpResponse("1")
if request.POST.get("remeber"):
res.set_cookie("username", username, max_age=7 * 24 * 3600)
res.set_cookie("pwd", pwd, max_age=7 * 24 * 3600)
return res
return HttpResponse("0")
5.emp相关功能实现
model操作:
class Emp(models.Model):
headpic = models.ImageField(upload_to="pics")
name = models.CharField(max_length=20)
salary = models.CharField(max_length=20)
age = models.IntegerField()
注:图片需指定存储位置,本文为 pics文件下(不需要自己创建,django会自动创建)
urls操作:
app_name = "emp"
urlpatterns = [
path("empList/", views.empList, name = "empList"),
path("addEmp/", views.addEmp, name = "addEmp"),
path("addEmpLogic/", views.addEmpLogic, name = "addEmpLogic"),
path("updateEmp/", views.updateEmp, name = "updateEmp"),
path("updateEmplogic/", views.updateEmplogic, name = "updateEmplogic"),
path("deleteEmp/", views.deleteEmp, name="deleteEmp"),
]
view操作:(创建视图函数)
主页面(查看):
def empList(request):
# 默认查看第一页,每页三条数据
number = request.GET.get("number", 1)
pagtor = Paginator(Emp.objects.all(), per_page=3)
# 判断是否为增加操作,如是,需要跳转到最后一页
if request.session.get("add"):
number = pagtor.num_pages
request.session['add'] = False
page = pagtor.page(number)
# 把页面对象传递给html页面
return render(request, 'emp/emplist.html', {'emps': page})
增加:
def addEmp(request):
return render(request, 'emp/addEmp.html')
增加判断操作:
def addEmpLogic(request):
# 获取属性参数
head_pic = request.FILES.get("head_pic")
name = request.POST.get("name")
salary = request.POST.get("salary")
age = request.POST.get("age")
# 设置图片名
head_pic.name = generteUUID(head_pic.name)
# 加入数据库事务
try:
with transaction.atomic():
Emp.objects.create(headpic=head_pic, name=name, salary=salary, age=age)
# 设置增加操作
request.session["add"] = True
return redirect('emp:empList')
except:
return HttpResponse("添加失败")
# 给图片头像设置随机文件名
def generteUUID(head_pic):
id = str(uuid.uuid4())
extend = os.path.splitext(head_pic)[1]
return id + extend
修改:
def updateEmp(request):
# 接收对应员工的id,和对应页数
id = request.GET.get("id")
page = request.GET.get("number")
request.session['number'] = page
emp = Emp.objects.get(id=id)
return render(request, "emp/updateEmp.html", {"emp": emp})
修改判断操作:
def updateEmplogic(request):
# 获取属性
id = request.POST.get("id")
head_pic = request.FILES.get("head_pic")
name = request.POST.get("name")
salary = request.POST.get("salary")
age = request.POST.get("age")
head_pic.name = generteUUID(head_pic.name)
# 修改数据库中的值,保存
emp = Emp.objects.get(id=id)
emp.headpic = head_pic
emp.name = name
emp.age = age
emp.salary = salary
emp.save()
# 传递页数给主页面
number = request.session.get('number')
url = reverse("emp:empList") + "?number=" + number
return redirect(url)
删除:
def deleteEmp(request):
# 删除对应员工,传递页数
id = request.GET.get("id")
number = request.GET.get("number")
Emp.objects.get(id=id).delete()
url = reverse("emp:empList") + "?number=" + number
return redirect(url)
6.template(模板文件):
1.在template下先创建相应app名文件
2.在app名文件下创建html页面
3.采取模板继承
base.html:
每个页面头部与尾部都是一样的,所以在父模板中渲染,如:右上角的时间
<script>
setInterval(function () {
var time = new Date()
var date = time.getFullYear() + "年" + (time.getMonth() + 1) + "月" + time.getDate() + "日" + time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds()
document.getElementById("time").innerHTML = date
}, 1000)
</script>
设置多个块,供子模版渲染
index.html:中javascript
<script>
{# 使用jQuery的ajax实现提交弹框 #}
function login_sub() {
var username = $("#username").val()
var pwd = $("#pwd").val()
var remeber = $("#remeber").prop("cheched")
$.ajax({
type: "POST",
url: "{% url 'user:loginlogic' %}",
data: "username=" + username + "&pwd=" + pwd + "&remeber=" + remeber +
"&csrfmiddlewaretoken=" + "{{ csrf_token }}",
success:function (msg) {
if (msg === '1'){
location.href = "{% url 'emp:empList' %}"
}else {
alert("用户名或密码错误!!!")
}
}
})
}
</script>
regist.html:的jquery
<script>
{#换一张验证码#}
function change() {
var url = "{% url 'user:getcaptcha' %}?" + new Date().getTime()
$("#num").attr('src',url)
}
{#提交弹框#}
function regist_sub() {
var username = $("#username").val()
var name = $("#name").val()
var pwd = $("#pwd").val()
var repwd = $("#repwd").val()
var sex = $("input[name='sex']:checked").val()
var number = $("#number").val()
$.ajax({
type:"POST",
url:"{% url 'user:registlogic' %}",
data:"username=" + username + "&name=" + name +"&pwd=" + pwd + "&repwd=" + repwd + "&sex=" + sex +"&number=" + number +
"&csrfmiddlewaretoken=" + "{{ csrf_token }}",
success:function (msg) {
if (msg === '1'){
location.href = "{% url 'emp:empList' %}"
}else {
alert("注册信息有误!!!")
}
}
})
}
{#三张图片:加载、正确、错误#}
var img1 = "{% static 'img/5-121204193934-50.gif' %}"
var img_right = "{% static 'img/right_3.jpg' %}"
var img_worry = "{% static 'img/5-140FG95153-51.gif' %}"
{#显示用户名输入后 相应的loading图片#}
function checkname(t) {
t.nextElementSibling.src = img1
$.ajax({
type: "POST",
url: "{% url 'user:checkname' %}",
data: "username=" + t.value + "&csrfmiddlewaretoken=" + "{{ csrf_token }}",
success:function (msg) {
if (msg === '1'){
t.nextElementSibling.src = img_right
}else {
t.nextElementSibling.src = img_worry
}
}
})
}
{#显示验证码输入后 相应的loading图片#}
function checknumber(t) {
t.nextElementSibling.src = img1
$.ajax({
type: "POST",
url: "{% url 'user:checknumber' %}",
data: "number=" + t.value + "&csrfmiddlewaretoken=" + "{{ csrf_token }}",
success:function (msg) {
if (msg === '1'){
t.nextElementSibling.src = img_right
}else {
t.nextElementSibling.src = img_worry
}
}
})
}
{#显示密码输入后 相应的loading图片#}
function checkpwd(t) {
t.nextElementSibling.src = img1
setTimeout(function () {
var content = t.value
if (content.length < 5){
t.nextElementSibling.src = img_worry
} else {
t.nextElementSibling.src = img_right
}
},1000)
}
{#显示确认密码输入后 相应的loading图片#}
function checkrepwd(t) {
t.nextElementSibling.src = img1
setTimeout(function () {
if (t.value === $("#repwd").val() && t.value !== ''){
t.nextElementSibling.src = img_right
} else {
t.nextElementSibling.src = img_worry
}
},1000)
}
</script>
empList.html:
jquery:
<script>
{#删除:判断是否是最后一条数据,进行页数减一#}
function del_emp(id) {
if(confirm("是否删除???")){
if ("{{ emps.start_index }}" === "{{ emps.end_index }}"){
var number = "{{ emps.number|add:'-1' }}"
}else {
var number = "{{ emps.number }}"
}
location.href = "{% url 'emp:deleteEmp' %}?number=" + number + "&id=" + id
}
}
</script>
html:
{#循环显示本页数据#}
{% for emp in emps.object_list %}
{# 每列交替换格式 #}
{% if forloop.counter|divisibleby:'2' %}
<tr class="row1">
{% else %}
<tr class="row2">
{% endif %}
{# 信息 #}
<td>{{ emp.id }}</td>
<td><img src="{% static emp.headpic.url %}" width="50px" height="50px"></td>
<td>{{ emp.name }}</td>
<td>{{ emp.salary }}</td>
<td>{{ emp.age }}</td>
{# 删除、修改 #}
<td>
<a href="javascript:void(0)" onclick="del_emp({{ emp.id }})">delete_emp</a>
<a href="{% url 'emp:updateEmp' %}?id={{ emp.id }}&number={{ emps.number }}">update_emp</a>
</td>
</tr>
{% endfor %}
{# 上一页 #}
{% if emps.has_previous %}
<a href="{% url 'emp:empList' %}?number={{ emps.previous_page_number }}">上一页</a>
{% endif %}
{# 页码 #}
{% for num in emps.paginator.page_range %}
<a href="{% url 'emp:empList' %}?number={{ num }}"></a>
{% if emps.number == num %}
<span class="a">{{ num }}</span>
{% else %}
<span class="b">{{ num }}</span>
{% endif %}
{% endfor %}
{# 下一页 #}
{% if emps.has_next %}
<a href="{% url 'emp:empList' %}?number={{ emps.next_page_number }}">下一页</a>
{% endif %}
以上为创建员工管理系统全部步骤及部分重要代码。前后端全部代码