跟b站武沛齐老师的视频学习 对学习过程进行一些记录以便复习 同时自我督促 :D冲鸭
视频链接: 15天django入门到放弃-哔哩哔哩.
回顾
对数据库的操作:pymysql、SQLAlchemy、navicat(终端)
-
安装 -
创建用户 + 授权 -
连接 - 数据库
终端创建数据库(字符编码)
- 数据表
终端、ORM、pymysql
pymysql:create ...(数据类型/是否可以为空/主键/自增/外键/索引)engine=innodb支持事务性操作
- 数据行
增、删、改、查
查:limit、group by、order by ...
关闭
内容概要
Web框架
- socket
- http协议
连接方式对比 HTTP:无状态、短连接 TCP:不断开 - HTML知识
- 数据库(pymysql、SQLAlchemy)
Web应用
-
浏览器(socket客户端) ② www.cnblogs.com(42.121.252.58,80) sk.socket()
sk.connect((42.121.252.58,80)
sk.send('我想要xx')
⑤ 接受 ⑥ 连接断开 -
博客园(socket服务端) ① 监听ip和端口(42.121.252.58,80) while True: – 用户 = 等待用户连接 – ③ 收到‘我想要xx’ – ④ 相应:“好” 用户断开
铺垫练习
s1 简单的byte传输
简单的数据传输。
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)
while True:
client_socket, client_addr = server_socket.accept()
data = client_socket.recv(8096)
response = "HTTP/1.1 200 OK\r\n\r\n"
client_socket.send(response.encode('utf8'))
client_socket.send(b'123123')
client_socket.send(bytes("hello", encoding='utf-8'))
client_socket.close()
s2 URL
对接收数据进行分割,提取出URL内容,实现不同URL页面显示不同文字。
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)
while True:
client_socket, client_addr = server_socket.accept()
data = client_socket.recv(8096)
data = str(data, encoding='utf-8')
headers, bodys = data.split('\r\n\r\n')
temp_list = headers.split('\r\n')
method, url, protocal = temp_list[0].split(' ')
response = "HTTP/1.1 200 OK\r\n\r\n"
client_socket.send(response.encode('utf8'))
if url == "/xxxx":
client_socket.send(b'123123')
else:
client_socket.send(b'404 not found')
client_socket.close()
s3 静态网站
在s2基础上,将文件作为data返回,实现更复杂的数据传输。 s3.python :
import socket
def f1():
"""
处理用户请求,并返回相应的内容
:param request: 用户请求的所有信息
:return:
"""
f = open('index.html', 'rb')
data = f.read()
f.close()
return data
def f2():
f = open('article.html', 'rb')
data = f.read()
f.close()
return data
def f3():
return b'word'
routers = [
('/index', f1),
('/article', f2),
('/word', f3)
]
def run():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)
while True:
client_socket, client_addr = server_socket.accept()
data = client_socket.recv(8096)
data = str(data, encoding='utf-8')
headers, bodys = data.split('\r\n\r\n')
temp_list = headers.split('\r\n')
method, url, protocal = temp_list[0].split(' ')
response_header = "HTTP/1.1 200 OK\r\n\r\n"
func_name = None
for item in routers:
if item[0] == url:
func_name = item[1]
break
if func_name:
response_body = func_name()
else:
response_body = b'404'
client_socket.send(response_header.encode('utf8'))
client_socket.send(response_body)
client_socket.close()
if __name__ == '__main__':
run()
article.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>article</title>
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<th>root</th>
<th>root@qq.com</th>
</tr>
</tbody>
</table>
</body>
</html>
index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>用户登录</h1>
<form>
<p><input type="text" placeholder="用户名" /></p>
<p><input type="password" placeholder="密码" /></p>
</form>
</body>
</html>
s4 动态网站
修改了 s3.py 中函数 f2() 和 f3() ,实现时间的显示和数据库内容的读取。
def f2():
f = open('time.html', 'r', encoding='utf-8')
data = f.read()
f.close()
import time
ctime = time.asctime(time.localtime(time.time()))
data = data.replace('@@time@@', str(ctime))
return bytes(data, encoding='utf-8')
def f3():
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id, username, password from userinfo")
user_list = cursor.fetchall()
conn.commit()
cursor.close()
conn.close()
print(user_list)
"""
要替换html文件中的@@content@
将数据库中读取的数据改写为格式如:
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
</tr>
"""
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 += tp
content = "".join(content_list)
f = open('userlist.html', 'r', encoding='utf-8')
template = f.read()
f.close()
data = template.replace('@@content@@', content)
return bytes(data, encoding='utf-8')
time.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>article</title>
</head>
<body>
<h1>@@time@@</h1>
</body>
</html>
userlist.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>article</title>
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
</tr>
</thead>
<tbody>
@@content@@
</tbody>
</table>
</body>
</html>
过渡性总结
自己写网站
- a. socket服务端
- b. 根据URL不同返回不同的内容
路由系统:URL -> 函数 - c. 字符串返回给用户
模板引擎渲染:HTML充当模板(特殊字符)、自己创造任意数据
Web框架
框架种类:
- abc
Tornado - [第三方a]+bc
Django (应用python中wsgiref模块) - [第三方ac]+b
flask(wsgiref、jinja2)
分类:
Django入门
创建项目
基本指令: 安装:pip3 install django
django-admin startproject mysite 若没有添加环境变量,要在路径下执行。
其他常用命令:
python manage.py runserver ip:port (启动服务器,默认ip和端口为http://127.0.0.1:8000/) python manage.py startapp appname (新建 app) python manage.py syncdb (同步数据库命令,Django 1.7及以上版本需要用以下的命令) python manage.py makemigrations (显示并记录所有数据的改动) python manage.py migrate (将改动更新到数据库) python manage.py createsuperuser (创建超级管理员) python manage.py dbshell (数据库命令行) python manage.py (查看命令列表)
项目建立完成得到如下文件夹:
mysite ├─── manage.py # 运行 └─── mysite ┈ ┈ ┈ ┈├─── __init__.py ┈ ┈ ┈ ┈├─── settings.py # 基本配置 ┈ ┈ ┈ ┈├─── urls.py # 路由系统 url -> 函数 ┈ ┈ ┈ ┈└─── wsgi.py # Web服务器网关接口 调用wsgiref模块 实现socket
基础配置
在 urls.py 文件中,urlpatterns 列表中增加路径; 引入 HttpResponse 模块,login 函数的返回值以此形式传递; 引入 HttpResponse 模块,可以读取其他文件,如 login.html 作为返回值。
from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse, render
def login(request):
"""
处理用户请求,并返回内容
:param request: 用户请求相关的所有信息(对象)
:return:
"""
return render(request, 'login.html')
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', login),
]
寻找文件的路径依据,在 settings.py 中 TEMPLATES 里进行了定义:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
...
templates 文件夹中的 login.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<h1 style="color: cadetblue">用户登录</h1>
<form>
<p><input type="text" placeholder="用户名" /></p>
<p><input type="password" placeholder="密码" /></p>
<p><input type="submit" value="登录"></p>
</form>
</body>
</html>
运行可看到页面: 也可以将样式写入CSS文件中,修改 login.html ,加入样式链接:
<link rel="stylesheet" href="/sta/commons.css">
在 sta 文件夹下新建 commons.css 文件:
h1{
color: cadetblue;
}
运行发现样式未应用,检查报错,发现CSS文件未能被找到;
原因是静态文件路径需要配置,在 setting.py 中最后修改静态路径:
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'sta'),
)
修改 login.html 中的链接:
<link rel="stylesheet" href="/static/commons.css">
再运行时,样式应用成功。
*将 sta 文件夹直接命名未 static 更加和谐统一,日后将所有静态文件放在 static 目录下。 (静态文件:图片、JS、CSS)
完善登录功能
login.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<link rel="stylesheet" href="/static/commons.css">
</head>
<body>
<h1>用户登录</h1>
<form method="post" action="/login/">
<p><input type="text" placeholder="用户名" name="username"/></p>
<p><input type="password" placeholder="密码" name="password"/></p>
<p><input type="submit" value="登录"></p>
{{ msg }}
</form>
</body>
</html>
这里用户端返回的消息形式:<QueryDict: {'username': ['root'], 'password': ['123123']}> urls.py :
def login(request):
"""
处理用户请求,并返回内容
:param request: 用户请求相关的所有信息(对象)
:return:
"""
if request.method == "GET":
return render(request, 'login.html', {'msg': '请输入用户名和密码'})
else:
"""
usr = request.POST['username']
psw = request.POST['password']
这样的方式并不好,取决于html文件中的name,如果不匹配会报错
"""
usr = request.POST.get('username')
psw = request.POST.get('password')
if usr == 'bernie' and psw == '123456':
return redirect('http://www.baidu.com')
else:
return render(request, 'login.html', {'msg': '用户名或密码错误'})
首次访问,请求形式为 GET ,将登录界面返回给用户;用户输入用户名和密码后,请求形式为 POST ,则进行判断,登录成功则借助 redirect 重定位跳转到指定网址;否则重新将登录界面返回给用户,并给出错误提示信息。
总结
1. 创建project
2. 配置
模板路径 - templates目录 静态文件路径 - static目录
3. 额外配置
将 MIDDLEWARE 中 'django.middleware.csrf.CsrfViewMiddleware', 注释掉
4. url对应关系
/login/ login
def login(request):
– request.method – request.POST ->请求体 – request.GET ->请求头中的url中 (GET请求:只有request.GET有值;POST请求:request.GET和request.POST都可能有值)
– return HttpResponse(…) – return render(request, ‘login.html’, {…}) – return redirect(‘要跳转的网址’或’/后缀/’)
5. 模板引擎的特殊标记
login.html {{name}}
def login(request): return render(request, ‘login.html’, {‘name’: ‘alex’})
html文件中的引用:
<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>
|