web网站:css
HTTP: 无状态、短连接(创建在TCP之上) TCP: 不断开(能够) WEB应用(网站): http协议: 发送 遵循请求头和请求体规则 GET发送方式 请求体在第一行/后面 GET /index/?p=3 HTTP/1.1
POST发送方式 请求体在请求头后结束空两行 POST /index/?p=3 HTTP/1.1
GET请求时----》 只有reqeuest.GET有值
POST请求 ----》 reqeuest.GET和reqeuest.POST均可能有值
响应 响应头 响应体 用户在页面看到的内容“字符串”(看到的效果,是浏览器解析的) WEB使用HTTP协议做应用层协议,以封装HTTP 文本信息,而后使用TCP/IP作传输层协议将它发到网络上。 浏览器(socket客户端) 2.www.cnblogs.com (DNS解析域名,拿到ip,42.121.252.58,80) 5.接收 6.连接断开 博客园(socket服务端) 1.监听ip和端口 3.收到 4.响应 7.收到用户断开连接
web框架:html
1. Http,无状态,短链接 2. 浏览器(socket客户端) 网站(socket服务端) 3. 本身写网站 a. socket服务端 b. 根据URL不一样返回不一样的内容 路由系统: URL -> 函数 c. 字符串返回给用户 模板引擎渲染: HTML充当模板(特殊字符) 本身创造任意数据 字符串 4. Web框架: 框架种类: - a,b,c --> Tornado - [第三方a],b,c --> wsgiref(做为服务端)-> Django - [第三方a],b,[第三方c] --> flask,jinja2
静态网站前端
import socket def f1(request): ''' 处理用户的请求,并返回相应的内容 request:用户请求的全部信息 ''' f = open('index.html','rb') data = f.read() f.close() return data def f2(request): f = open('article.html', 'rb') data = f.read() f.close() return data routers = [ ('/xxx',f1), ('/ooo',f2), ] def run(): sock = socket.socket() sock.bind(('127.0.0.1',8080)) sock.listen(5) while True: conn,addr = sock.accept() #等待连接 data =conn.recv(8096) data = str(data,encoding='utf-8') print(data) headers,bodys=data.split('\r\n\r\n') temp_list=headers.split('\r\n') method,url,protecal = temp_list[0].split(' ') conn.send(b"HTTP/1.1 200 OK\r\n\r\n") # 响应头 fun_name = None for item in routers: if item[0]==url: fun_name = item[1] break if fun_name: response = fun_name(data) else: response = b"404" conn.send(response) # if url == "/xxxx": # conn.send(b'123123') # else: # conn.send(b'404 not find') conn.close() if __name__ == '__main__': run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用户登陆</h1> <form action=""> <p><input type="text" placeholder="用户名"></p> <p><input type="password" placeholder="密码"></p> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1"> <thead> <tr> <th>1</th> <th>root</th> <th>root@qq.com</th> </tr> </thead> </table> </body> </html>
动态网站(从数据库取数据)python
import socket def f1(request):#静态网站 ''' 处理用户的请求,并返回相应的内容 request:用户请求的全部信息 ''' f = open('index.html','rb',) data = f.read() f.close() return data def f2(request):#动态网站 f = open('article.html', 'r',encoding='utf-8') data = f.read() f.close() import time ctime = time.time() data = data.replace("@@sw@@",str(ctime)) return bytes(data,encoding='utf-8') def f3(request): #去数据库取数据 import pymysql # 建立链接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='db666') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id,username,password from userinfo") user_list = cursor.fetchall() cursor.close() conn.close() content_list = [] for row in user_list: tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" %(row['id'],row['username'],row['password']) content_list.append(tp) content = "".join(content_list) f = open('userlist.html','r',encoding='utf-8') template = f.read() f.close() # 模板渲染(模板+数据) data = template.replace('@@sdfsdffd@@',content) return bytes(data,encoding='utf-8') def f4(request): # 基于第三方工具实现的模板渲染jinja2 import pymysql # 建立链接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='db666') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id,username,password from userinfo") user_list = cursor.fetchall() cursor.close() conn.close() f = open('hostlist.html','r',encoding='utf-8') data = f.read() f.close() # 基于第三方工具实现的模板渲染jinja2 #data就是模板 from jinja2 import Template template = Template(data) data = template.render(xxxxx=user_list,user='sdfsdfsdf') return data.encode('utf-8') routers = [ ('/xxx',f1), ('/aaa',f2), ('/userlist.htm', f3), ('/host.html', f4), ] def run(): sock = socket.socket() sock.bind(('127.0.0.1',8080)) sock.listen(5) while True: conn,addr = sock.accept() #等待连接 data =conn.recv(8096) data = str(data,encoding='utf-8') headers,bodys=data.split('\r\n\r\n') temp_list=headers.split('\r\n') method,url,protecal = temp_list[0].split(' ') conn.send(b"HTTP/1.1 200 OK\r\n\r\n") # 响应头 fun_name = None for item in routers: if item[0]==url: fun_name = item[1] break if fun_name: response = fun_name(data) else: response = b"404" conn.send(response) # if url == "/xxxx": # conn.send(b'123123') # else: # conn.send(b'404 not find') conn.close() if __name__ == '__main__': run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用户登陆</h1> <form action=""> <p><input type="text" placeholder="用户名"></p> <p><input type="password" placeholder="密码"></p> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <table border="1"> <thead> <tr> <th>ID</th> <th>用户名</th> <th>邮箱</th> </tr> </thead> <tbody> {% for row in xxxxx %} <!--循环--> <tr> <td>{{row.id}}</td> <td>{{row.username}}</td> <td>{{row.password}}</td> </tr> {% endfor %} </tbody> </table> {{user}} </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1"> <thead> <tr> <th>id</th> <th>用户</th> <th>邮箱</th> </tr> </thead> <tbody> <tr> <th>1</th> <th>@@sw@@</th> <th>root@qq.com</th> </tr> </tbody> </table> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <table border="1"> <thead> <tr> <th>ID</th> <th>用户名</th> <th>邮箱</th> </tr> </thead> <tbody> @@sdfsdffd@@ </tbody> </table> </body> </html>
Django框架:mysql
pip3 install django 在终端安装程序后,将django-admin.py文件的上一级路径加环境变量里面 命令: # 建立Django程序 django-admin startproject mysite # 进入程序目录 cd mysite # 启动socket服务端,等待用户发送请求 python manage.py runserver 127.0.0.1:8080 启动服务端,监听端口,等待连接 默认端口是8000 pycharm: ... Django程序目录: mysite mysite - settings.py # Django配置文件 - url.py # 路由系统:url和函数的对应关系 - wsgi.py # 用于定义Django用socket, 默认用的wsgiref,用于本地测试,工做时用uwsgi manage.py # 对当前Django程序全部操做能够基于 python manage.py runserver ,还能够加其余参数
1. Web框架本质 浏览器(socket客户端) 2. 发送IP和端口 http://www.baidu.com:80/index/ GET: 请求头 http1.1 /index?p=123 ... 请求体(无内容) POST: 请求头 http1.1 /index?p=123 ... 请求体 ... 4. 接收响应 普通响应:页面直接显示 重定向响应:再一块儿一次Http请求(服务端传回客户端,再向服务端发起一次Http请求) 服务器(socket服务端) 1. 启动并监听ip和端口,等待用户链接 3. 接收请求进行处理,并返回 普通返回: 响应头: Access-Control-Allow-Origin:* Cache-Control:max-age=600 Date:Mon, 19 Jun 2017 00:57:43 GMT Expires:Mon, 19 Jun 2017 01:07:43 GMT Last-Modified:Wed, 24 May 2017 01:51:55 GMT Server:GitHub.com X-GitHub-Request-Id:C495:5EBC:8739EF:B817EE:59472187 响应体: <html> .... </html> 重定向返回: 响应头: LOCATION: 'http://www.baidu.com' Access-Control-Allow-Origin:* Cache-Control:max-age=600 Date:Mon, 19 Jun 2017 00:57:43 GMT Expires:Mon, 19 Jun 2017 01:07:43 GMT Last-Modified:Wed, 24 May 2017 01:51:55 GMT Server:GitHub.com X-GitHub-Request-Id:C495:5EBC:8739EF:B817EE:59472187 2. DjangoWeb框架 a. 建立Project django-admin startproject mysite b. 配置 模板 静态文件 csrf c. 路由关系 url -> 函数 url -> 函数 url -> 函数 url -> 函数 d. 视图函数 def index(request): request.method request.GET.get('name') request.POST.get('nage') li = request.POST.getlist('多选下拉框name') return HttpResponse('字符串') return redirect('URL') return render(request,'模板路径',{}) # 1. 获取模板+数据,渲染 # 2. HttpReponse(...) c. 模板渲染 {{k1}} {{k2.0}} {% for i in result %} {{i}} {%endfor %} {%if 1>2%} {%endif%} 3. Ajax(jQuery) $.ajax({ url: '', type: 'GET', data: {k1:'v1'}, success:function(arg){ } })
配置:jquery
- 模板路径 template目录 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'template')], #模板路径设置 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] - 静态文件路径 static目录 STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )#静态文件路径设置
额外配置:web
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
urls.pyajax
from django.conf.urls import url from django.contrib import admin from django.shortcuts import HttpResponse,render,redirect def login(request): """ 处理用户请求,并返回内容 :param request: 用户请求相关的全部信息(对象) :return: """ # HttpResponse只处理字符串 # return HttpResponse('<input type="text" />') # return HttpResponse('login.html') # render自动找到模板路径下的login.html文件,读取内容并返回给用户 # 模板路径的配置(settings.py内'DIRS') print(request.GET) if request.method == "GET": return render(request,'login.html') else: # request.POST用户POST提交的数据(请求体) u = request.POST.get('user') #get方式取值,若是没有不会报错,会赋值None p = request.POST.get('pwd') if u == 'root' and p == '123123': # 登陆成功 # return redirect('http://www.oldboyedu.com') 跳转网页 return redirect('/index/') #跳转 else: # 登陆失败 return render(request,'login.html',{'msg': '用户名或密码错误'}) #msg模板引擎的特殊标记 def index(request): # return HttpResponse('Index') return render( request, 'index.html', { 'name': 'alex', 'users':['李志','李杰'], 'user_dict':{'k1': 'v1','k2':'v2'}, 'user_list_dict': [ {'id':1, 'name': 'alex', 'email': 'alex3714@163.com'}, {'id':2, 'name': 'alex2', 'email': 'alex3714@1632.com'}, {'id':3, 'name': 'alex3', 'email': 'alex3713@1632.com'}, ] } ) urlpatterns = [ # url(r'^admin/', admin.site.urls),#目前用不着 url(r'^login/', login), url(r'^index/', index), ]
static-----静态文件,放置插件、css、js文件等sql
h1{
color: red;
}
templates---模板数据库
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>模板标记学习</h1> <p>{{ name }}</p> <p>{{ users.0 }}</p> <p>{{ users.1 }}</p> {# 列表特殊取值方式#} <p>{{ user_dict.k1 }}</p> 字典的特殊取值方式 <p>{{ user_dict.k2 }}</p> <h3>循环</h3> <ul> {% for item in users %} <li>{{ item }}</li> {% endfor %} {# 循环的取值方式#} </ul> <h3>循环</h3> <table border="1"> {% for row in user_list_dict %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td> <a>编辑</a> | <a href="/del/?nid={{ row.id }}">删除</a> </td> </tr> {% endfor %} </table> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="/static/commons.css" /> </head> <body> <h1>用户登陆</h1> <form method="POST" action="/login/"> {# action是提交路径#} <input type="text" name="user" /> <input type="password" name="pwd" /> <input type="submit" value="登陆" /> {{ msg }} {# render传值才显示#} </form> </body> </html>
- 模板渲染 def index(request): return render(request,'模板路径', { 'k1': 'v1', 'k2': [1,2,32,34], 'k3': {'x'...}, } ) index.html <h1>{{k1}}</h1> <h1>{{k2.2}}</h1> {% for item in k2%} <h1>{{item}}</h1> {% endfor %}
1. 模态对话框 - 添加 Form表单提交,页面会刷新 2. Ajax(不要以Form表单提交,完成模态对话框提交失败,返回信息还在模态对话框,不刷新网页) jQuery $.ajax({ url: '要提交的地址', type: 'POST', // GET或POST,提交方式 data: {'k1': 'v1','k2':'v2'}, // 提交的数据 dataType:"JSON",//默认将服务端传回的字符串转化为对象
success:function(data){ // 当前服务端处理完毕后,自动执行的回调函数 // data返回的数据 //data字符串类型
//JSON.parse(字符串)==》对象
//JSON.stringify(对象)==》字符串
//arg = JSON.parse(data);
if(data.status){
//location.href='/class/' //从定向
location.reload()//刷新当前页面
}
else{
$("#errormsg").text(data.message)
}
} }) 其余: 1. 模板语言if条件语句和循环语句
{% for row in class_list %}
{% if row.id == student_info.id %}
<option selected value="{{ row.id }}">{{ row.title }}</option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endif %}
{% endfor %}
索引[11,22,33].indexOf(22222) 正确的话返回索引位置,不正确的话返回-1
{{}}
2. Form表单提交,页面会刷新 3. Ajax提交页面不刷新 4. js实现页面跳转: location.href = "要跳转的地址" 5. 模态对话框(Ajax) - 少许输入框 - 数据少 登陆 新URL方式 - 操做多 - 对于大量的数据以及操做
6.多对多时(例如老师授课班级关系表编辑时,更新老师和班级关系表时,解决方法):
1、删除原先老师授课班级的关系表,而后再插入授课班级关系表
2、print list(set(b).difference(set(a))) 判断修改的授课关系表是否在数据库中,不在再插入
1. Http请求生命周期 请求头 -> 提取URL -> 路由关系匹配 -> 函数 (模板+数据渲染) -> 返回用户(响应头+响应体) 2. def index(request): request.POST.getlist 获取列表数据
request.GET.get request.method 判断数据的传输方法
return render() 模板渲染(结合html文件)
return HttpResponse() 传输字符串
return redirect() 向客户端发送响应体,再让客户端发起一次http请求
补充:模板渲染是在后台执行
先执行函数,再跳转网页:
<a href="www.baidu.com" onclick="btn">点击</a> <script> function btn() { alert(123) } </script>
事件执行后,再也不跳转(js):
<a href="www.baidu.com" onclick="return btn">点击</a> <script> function btn() { alert(123); return false } </script>
事件执行后,再也不跳转(Jquery):
<a href="www.baidu.com" id="'#addModal'">点击</a>
$('#addModal').click(function(){ alert(123); return false; })
服务端:
def edi_class(request): ret = {"status":True,"message":None} try: nid = request.POST.get("nid") print(nid) title=request.POST.get("title") print(title) conn = pymysql.connect(host="localhost", user="root", password="", database="class_student",
charset="utf8") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("update class set title=%s where id=%s ", [title,nid, ]) conn.commit() cursor.close() conn.close() except Exception as e: ret["status"]=False ret["message"]=e; return HttpResponse(json.dumps(ret))
客户端:
csrftoken的取值用插件的形式取
<script src="/static/jquery.cookie.js"></script>
function AjaxSend_edi(){ var token = $.cookie('csrftoken');
$.ajax({ url: '/edi_class/', type: 'POST', headers: {'X-CSRFToken': token},
data: {'nid': $('.modal_edi_Y').attr("nid"),'title':$('.modal_edi_title').val()}, dataType:"JSON", success:function (arg) { //arg字符串类型 //JSON.parse(字符串)==》对象 //JSON.stringify(对象)==》字符串 //arg = JSON.parse(arg); if(arg.status){ //location.href='/class/' location.reload() } else{ $("#errormsg").text(arg.message) } } }) }
或者(csrftoken的取值方式不一样)
function AjaxSend_edi(){
$.ajax({ url: '/report.html', type: "POST", data: {'csrfmiddlewaretoken': '{{ csrf_token }}'}, dataType: 'JSON', success: function (arg) { console.log(arg); }, }); }
$.getJSON( "{% url 'get_task_result' %}", {'task_id':task_id}, function(callback){} ) $.post( "{% url 'multitask' %}", {'csrfmiddlewaretoken': "{{ csrf_token }}",'task_data': JSON.stringify(task_data)}, function(callback){} )
url方式接收时select的多个选项时:
class_id=request.POST.getlist("class_id")
Ajax方式时有两种解决方法:
function bindAddSubmit(){ $('#addSubmit').click(function(){ var name = $('#addName').val(); var class_id_list = $('#classIds').val(); console.log(name,class_id_list); $.ajax({ url:'/modal_add_teacher/', type: 'POST', data: {'name':name, 'class_id_list': class_id_list,'csrfmiddlewaretoken': '{{ csrf_token }}'}, dataType:'JSON', traditional: true,// 若是提交的数据的值有列表,则须要添加此属性 //不加这个属性时,jQuery1.4以后可序化,数组参数名自动添加[] success: function (arg) { if(arg.status){ location.reload(); }else{ alert(arg.message); } } }) }); }
1、在html中添加
traditional: true
2、在服务端接收时:
class_id=request.POST.getlist("class_id_list[]")
1、bootstrap
引入:
bootstrap.css测试时用
bootstrap.min.css生产时用
2、ontawesome
引入:
font-awesome.css
import pymysql def get_list(sql,args): conn = pymysql.connect(host="localhost",user="root",password="",charset="utf8",database="class_student") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) result = cursor.fetchall() cursor.close() conn.close() return result def get_one(sql,args): conn = pymysql.connect(host="localhost",user='root',password='',charset='utf8',database='class_student') cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) result=cursor.fetchone() cursor.close() conn.close() return result def modify(sql,args): conn = pymysql.connect(host="localhost", user='root', password='', charset='utf8', database='class_student') cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) conn.commit() cursor.close() conn.close() def create(sql,args): conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='class_student', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) conn.commit() last_row_id = cursor.lastrowid cursor.close() conn.close() return last_row_id
import pymysql class SqlHelper(object): def __init__(self): # 读取配置文件 self.connect() def connect(self): self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='class_student', charset='utf8') self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) def get_list(self,sql,args): self.cursor.execute(sql,args) result = self.cursor.fetchall() return result def get_one(self,sql,args): self.cursor.execute(sql,args) result = self.cursor.fetchone() return result def modify(self,sql,args): self.cursor.execute(sql,args) self.conn.commit() def multiple_modify(self,sql,args): # self.cursor.executemany('insert into bd(id,name)values(%s,%s)',[(1,'alex'),(2,'eric')]) self.cursor.executemany(sql,args) self.conn.commit() def create(self,sql,args): self.cursor.execute(sql,args) self.conn.commit() return self.cursor.lastrowid def close(self): self.cursor.close() self.conn.close()