管理员操作
管理员账户
models.py
class Admin(models.Model):
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
urls.py
urlpatterns = [
#管理员账户
path('admin/list/', admin.admin_list),
]
templates/layout.html
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="/admin/list/">管理员账户</a></li>
<li><a href="/depart/list/">部门管理</a></li>
<li><a href="/user/list/">用户管理</a></li>
<li><a href="/pretty/list/">靓号管理</a></li>
</ul>
views/admin.py
from django.shortcuts import render
from app01 import models
def admin_list(request):
queryset = models.Admin.objects.all()
context={
"queryset":queryset
}
return render(request,"admin_list.html",context)
templates/admin_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px;">
<a class="btn btn-success" href="/admin/add/">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新建管理员
</a>
<div style="float:right; width:300px;">
<form method="get">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search for..." value="{
{search_data}}">
<span class="input-group-btn">
<button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search"
aria-hidden="true"></span></button>
</span>
</div><!-- /input-group -->
</form>
</div>
</div>
<div class="bs-example" data-example-id="table-within-panel">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
管理员列表
</div>
<!-- Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for obj in queryset %}
<tr>
<th>{
{obj.id}}</th>
<td>{
{obj.username}}</td>
<td>{
{obj.password}}</td>
<td>
<a class="btn btn-primary btn-xs" href="/admin/{
{obj.id}}/edit/">编辑 </a>
<a class="btn btn-danger btn-xs" href="/admin/{
{obj.id}}/delete/">删除 </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="clearfix">
<ul class="pagination">
{
{page_string}}
</ul>
</div>
</div>
</div>
{% endblock %}
新建管理员
urls.py
urlpatterns = [
#管理员账户
path('admin/list/', admin.admin_list),
path('admin/add/', admin.admin_add),
]
views/admin.py
def admin_add(request):
# 添加管理员
title="新建管理员"
if request.method == "GET":
form = AdminModelForm()
return render(request, 'change.html', {"form": form,"title":title})
# 用户POST提交数据,密码校验
form = AdminModelForm(data=request.POST)
if form.is_valid():
# print(form.cleaned_data)
form.save()
return redirect("/admin/list/")
else:
return render(request, 'change.html', {"form": form,"title":title})
utils/form.py
class AdminModelForm(BootstrapModelForm):
confirm_password = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(render_value=True)
)
class Meta:
model = models.Admin
fields = ["username", "password","confirm_password"]
widgets={
"password":forms.PasswordInput(render_value=True)
}
def clean_password(self):
pwd= self.cleaned_data.get("password")
return md5(pwd)
def clean_confirm_password(self):
pwd = self.cleaned_data.get("password")
confirm = md5(self.cleaned_data.get("confirm_password"))
if pwd!=confirm:
raise ValidationError("两次密码不一致")
# 返回什么此字段保存到数据库就是什么
return confirm
utils/encrypt.py
import hashlib
from django.conf import settings
def md5(data_string):
obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
obj.update(data_string.encode('utf-8'))
return obj.hexdigest()
templates/change.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{
{title}}</h3>
</div>
<div class="panel-body">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{
{field.label}}</label>
{
{field}}
<span style="color:red;">{
{field.errors.0}}</span>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">提交</button>
</form>
</div>
</div>
</div>
{% endblock %}
编辑管理员
views/admin.py
def admin_edit(request, nid):
# 编辑管理员
title="编辑管理员"
row_object = models.Admin.objects.filter(id=nid).first()
if not row_object:
return redirect('/admin/list/')
if request.method == "GET":
# instance=row_object显示默认值
form = AdminModelForm(instance=row_object)
return render(request, 'change.html', {"form": form,"title":title})
form = AdminModelForm(data=request.POST, instance=row_object)
if form.is_valid():
form.save()
return redirect('/admin/list/')
return render(request, 'change.html', {"form": form,"title":title})
urls.py
urlpatterns = [
#管理员账户
path('admin/list/', admin.admin_list),
path('admin/add/', admin.admin_add),
path('admin/<int:nid>/edit/', admin.admin_edit),
]
删除管理员
urls.py
urlpatterns = [
#管理员账户
path('admin/list/', admin.admin_list),
path('admin/add/', admin.admin_add),
path('admin/<int:nid>/edit/', admin.admin_edit),
path('admin/<int:nid>/delete/', admin.admin_delete),
]
views/admin.py
def admin_delete(request, nid):
# 删除部门
models.Admin.objects.filter(id=nid).delete()
return redirect('/admin/list/')
Cookie和Session
cookie:【浏览器】保存在浏览器上的键值对,发送请求时自动携带
session:【网站】存储凭证(数据库、redis、文件),如果请求的凭证存在,返回信息
用户认证
基本实现
urls.py
urlpatterns = [
#用户认证
path('login/', account.login),
]
templates/login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.css' %}">
<style>
.account {
width: 400px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 5px 5px 20px #aaa;
margin-left: auto;
margin-right: auto;
margin-top: 100px;
padding: 20px 40px;
}
.account h2 {
margin-top: 10px;
text-align: center;
}
</style>
</head>
<body>
<div class="account">
<h2>用户登录</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名</label>
{
{form.username}}
<span style="color:red;">{
{form.username.errors.0}}</span>
</div>
<div class="form-group">
<label>密码</label>
{
{form.password}}
<span style="color:red;">{
{form.password.errors.0}}</span>
</div>
<input type="submit" class="btn btn-default" value="登 录">
</form>
</div>
</body>
</html>
views/account.py
from django.shortcuts import render, redirect
from django import forms
from app01 import models
from app01.utils.bootstrap import BootstrapForm
from app01.utils.encrypt import md5
class LoginForm(BootstrapForm):
username = forms.CharField(
label="用户名",
widget=forms.TextInput
)
password = forms.CharField(
label="密码",
widget=forms.PasswordInput
)
def clean_password(self):
pwd=self.cleaned_data.get("password")
return md5(pwd)
def login(request):
if request.method=="GET":
form = LoginForm()
return render(request, "login.html", {"form": form})
form=LoginForm(data=request.POST)
if form.is_valid():
admin_object=models.Admin.objects.filter(**form.cleaned_data).first()
if not admin_object:
form.add_error("password","用户名或密码错误")
return render(request,'login.html',{'form':form})
# 用户验证通过,将他写到cookie中,再写到session中
request.session["info"]={"id":admin_object.username,"username":admin_object.username}
return redirect("/admin/list/")
return render(request,'login.html',{'form':form})
中间件处理
登录成功后,在cookie中写随机字符串,在session中存用户信息
在其他需要登录才能访问的页面中,都需要加入:
# 检查用户是否已登陆,未登录返回登陆页面
# 用户发来请求,获取cookie随机字符串,拿着随机字符串看session中有无
info = request.session.get("info")
if not info:
return redirect("/login/")
目标:在视图函数前统一加入判断
中间件是个类,其中定义了方法process_request和process_response,浏览器请求经过中间件的process_request,然后执行视图函数,将视图函数的结果经过process_response再返还给浏览器
utils/auth.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
class AuthMiddleware(MiddlewareMixin):
def process_request(self,request):
# 0、排除不需要登录就能访问的页面
if request.path_info=="/login/":
return
# 1\读取当前访问用户的session信息,如果能读到,说明登录过,可以继续向后走
info_dict = request.session.get("info")
if info_dict:
return
# 2\没有登录过,跳到登录页面
return redirect("/login/")
def process_response(self,request,response):
return response
settings.py
MIDDLEWARE = [
'app01.middleware.auth.AuthMiddleware',
]
注销
就是将cookie和session中去除
urls.py
#用户认证
path('login/', account.login),
path('logout/', account.logout),
views/account.py
def logout(request):
request.session.clear()
return redirect('/login/')
Ajax请求
浏览器向网站发送请求时:URL和表单的提交形式
- GET
- POST
也可以通过ajax向后台发请求
1、依赖jquery,编写ajax代码
$.ajax({
url:"发送地址",
type:"post",
data:{
n1:123,
n2:456
},
success:function(res){
console.log(res);
}
})
任务管理
GET请求
urls.py
urlpatterns = [
#任务管理
path('task/list/',task.task_list),
]
views/task.py
from django.shortcuts import render, redirect
def task_list(request):
return render(request,"task_list.html")
tempaltes/task_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<h1>任务管理</h1>
<h3>示例1</h3>
<input type="button" class="btn btn-primary" value="点击" οnclick="clickMe();" />
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
function clickMe(){
$.ajax({
url: '/task/ajax/',
type:"get",
data:{
n1:123,
n2:456
},
success: function(res){
console.log(res);
}
});
}
</script>
{% endblock %}
POST请求
需要免除csrf验证
views/task.py
from django.shortcuts import render, redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def task_ajax(request):
print(request.GET)
print(request.POST)
return HttpResponse("chengong")
templates/task_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<h1>任务管理</h1>
<h3>示例1</h3>
<input type="button" class="btn btn-primary" value="点击" id="btn1" />
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
// 页面框架加载完成之后代码自动执行
$(function(){
bindBtn1Event();
})
// 页面加载完成后,给btn绑定一个
function bindBtn1Event(){
$("#btn1").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:{
n1:123,
n2:456
},
success: function(res){
console.log(res);
}
});
})
}
</script>
{% endblock %}
ajax请求的返回值
一般会返回json格式
/task_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<h1>任务管理</h1>
<h3>示例1</h3>
<input type="button" class="btn btn-primary" value="点击" id="btn1"/>
<h3>示例2</h3>
<input type="text" id="txtUser" placeholder="姓名"/>
<input type="text" id="txtAge" placeholder="年龄"/>
<input type="button" class="btn btn-primary" value="点击" id="btn2"/>
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
// 页面框架加载完成之后代码自动执行
$(function(){
bindBtn1Event();
bindBtn2Event();
})
// 页面加载完成后,给btn绑定一个
function bindBtn1Event(){
$("#btn1").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:{
n1:123,
n2:456
},
dataType:"JSON",
success: function(res){
console.log(res);
console.log(res.status);
console.log(res.data);
}
});
})
}
function bindBtn2Event(){
$("#btn2").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:{
n1:$("#txtUser").val(),
n2:$("#txtAge").val()
},
dataType:"JSON",
success: function(res){
console.log(res);
console.log(res.status);
console.log(res.data);
}
});
})
}
</script>
{% endblock %}
views/task.py
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def task_ajax(request):
print(request.GET)
print(request.POST)
data_dict = {"status": True, "data": [11, 22, 33, 44]}
return JsonResponse(data_dict)
创建任务
models.py
class Task(models.Model):
level_choices = (
(1, "1级"),
(2, "2级"),
(3, "3级"),
)
level = models.IntegerField(verbose_name="级别", choices=level_choices, default=1)
title = models.CharField(verbose_name="标题", max_length=64)
detail = models.TextField(verbose_name="详细信息")
user= models.ForeignKey(verbose_name="负责人",to="Admin",on_delete=models.CASCADE)
utils/task.py
@csrf_exempt
def task_add(request):
# print(request.POST)
# 1、用户发送过来的数据进行校验,(ModelForm进行校验)
form = TaskModelForm(data=request.POST)
if form.is_valid():
form.save()
data_dict = {"status": True}
return HttpResponse(json.dumps(data_dict))
data_dict = {"status":False,'errors':form.errors}
return HttpResponse(json.dumps(data_dict,ensure_ascii=False))
templates/task_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">新建表单</div>
<div class="panel-body">
<div class="clearfix">
<form id="formAdd" novalidate>
{% for field in form %}
<div class="col-xs-6">
<div class="form-group" style="position: relative;margin-bottom: 20px;">
<label>{
{field.label}}</label>
{
{field}}
<span class="error-msg" style="color:red; position: absolute;"></span>
</div>
</div>
{% endfor %}
<div class="col-xs-12">
<button type="button" id="btnAdd" class="btn btn-primary">提交</button>
</div>
</form>
</div>
</div>
</div>
<h1>Ajax学习</h1>
<h3>示例1</h3>
<input type="button" class="btn btn-primary" value="点击" id="btn1"/>
<h3>示例2</h3>
<input type="text" id="txtUser" placeholder="姓名"/>
<input type="text" id="txtAge" placeholder="年龄"/>
<input type="button" class="btn btn-primary" value="点击" id="btn2"/>
<h3>示例3</h3>
<form id="form3">
<input type="text" name="txtUser" placeholder="姓名"/>
<input type="text" name="txtAge" placeholder="年龄"/>
<input type="text" name="txtEmail" placeholder="邮箱"/>
<input type="text" name="txtMore" placeholder="更多"/>
<input type="button" class="btn btn-primary" value="点击" id="btn3"/>
</form>
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
// 页面框架加载完成之后代码自动执行
$(function(){
bindBtn1Event();
bindBtn2Event();
bindBtn3Event();
bindBtnAddEvent();
})
// 页面加载完成后,给btn绑定一个
function bindBtn1Event(){
$("#btn1").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:{
n1:123,
n2:456
},
dataType:"JSON",
success: function(res){
console.log(res);
console.log(res.status);
console.log(res.data);
}
});
})
}
function bindBtn2Event(){
$("#btn2").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:{
n1:$("#txtUser").val(),
n2:$("#txtAge").val()
},
dataType:"JSON",
success: function(res){
console.log(res);
console.log(res.status);
console.log(res.data);
}
});
})
}
function bindBtn3Event(){
$("#btn3").click(function(){
$.ajax({
url: '/task/ajax/',
type:"post",
data:$("#form3").serialize(),
dataType:"JSON",
success: function(res){
console.log(res);
console.log(res.status);
console.log(res.data);
}
});
})
}
function bindBtnAddEvent(){
$("#btnAdd").click(function(){
$(".error-msg").empty();
$.ajax({
url: '/task/add/',
type:"post",
data:$("#formAdd").serialize(),
dataType:"JSON",
success: function(res){
if(res.status){
alert("添加成功")
}
else{
$.each(res.errors,function(name,data){
// console.log(name,data)
$("#id_"+name).next().text(data[0]);
})
}
}
});
})
}
</script>
{% endblock %}