开发工程师必备————【Day23】web框架(动静态及jinja2模块)django基本操作命令及三板斧

今日内容概要

  • 纯手撸web框架
  • 基于wsgiref模块
  • 框架代码优化
  • 动静态网页
  • jinja2模板语法
  • python主流web框架
  • django框架简介
  • django基本操作命令
  • django小白必会三板斧

纯手撸web框架

1.web框架概念
web框架可以理解为是基于互联网的web服务端(socket服务端)

2.步骤

  • socket服务端代码
  • HTTP协议
  • 根据网址后缀的不同请求不同的内容
  • 请求方式
    (1)GET:朝服务端索要数据
    (2)POST:朝服务端提交数据
  • 从请求数据格式中筛选出用户输入的网址后缀
target_url = data.decode('utf8').split(' ')[1]
  • 代码的缺陷:
    (1)socket代码重复编写造轮子
    (2)针对请求数据格式的处理复杂且重复
    (3)针对不同网址后缀的匹配方式过于简单

3.未优化代码展示

import socket

server = socket.socket()  # TCP协议
server.bind(('127.0.0.1', 8080))  # IP协议 PORT协议
server.listen(5)  # 连接池

while True:
   sock, address = server.accept()
   data = sock.recv(1024)
   sock.send(b'HTTP/1.1 200 OK\r\n\r\n')
   # print(data.decode('utf8'))  # 从字符串中截取出需要的内容
   target_url = data.decode('utf8').split(' ')[1]  # / /index /login /reg /xxx
   if target_url == '/index':
       sock.send(b'index view')
       #  with open(r'my html.html','rb') as f:
        #  sock.send(f.read())
   elif target_url == '/login':
      sock.send(b'login view')
   elif target_url == '/reg':
       sock.send(b'reg view')
   else:
       sock.send(b'404 error')

基于wsgiref模块

wsgiref内置模块:
wsgiref内部封装了socket代码和对请求数据的处理。

from wsgiref.simple_server import make_server

def run(request, response):
   """
   :param request: 请求数据
   :param response: 响应数据
   :return: 返回给客户端的数据
   """
   print(request)  # 自动将请求数据全部处理成字典k:v键值对形式
   response('200 OK', [])  # 固定代码 无需掌握
   return [b'hello big baby']


if __name__ == '__main__':
   server = make_server('127.0.0.1', 8080, run)  # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用
   server.serve_forever()  # 永久启动
  • wsgiref模块解决了两个问题:
    (1)socket代码重复编写造轮子
    (2)针对请求数据格式的处理复杂且重复
  • 思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)
    先从大字典中查找出记录网址后缀的键值对。
    (1)不推荐使用连续的多个if判断
    (2)针对面条版的代码首先应该考虑封装成函数
def index(request):
    return 'index'
def login(request):
    return 'login'
def register(request):
    return 'register'
def error(request):
    return '404 error' 
urls = (
    ('/index', index),
    ('/login', login),
    ('/register', register),
)	
  • 根据py文件中功能的不同划分到不同的py文件(模块化)
py文件功能
urls.py对应关系
views.py功能函数
start.py启动文件
templates文件夹存储html

封装之后的最终代码

启动文件 (start.py )from wsgiref.simple_server import make_server
from urls import urls
from views import *

def run(request, response):
   response('200 OK', [])
   target_path = request.get('PATH_INFO')  # /login
   func_name = None
   for url_tuple in urls:  # ('/index',index)    ('/login',login)
       if url_tuple[0] == target_path:
           func_name = url_tuple[1]  # 先存储匹配到的函数名
           break  # 一旦匹配到了内容立刻结束for循环
   # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上)
   if func_name:
       res = func_name(request)
   else:
       res = error(request)
   return [res.encode('utf8')]  # 作统一编码处理


if __name__ == '__main__':
  server = make_server('127.0.0.1', 8080, run)  # 任何访问>127.0.0.1:8080的请求都会给第三个参数加括号调用
  server.serve_forever()  # 永久启动
功能函数(views.py )

def index(request):
   return 'index'


def login(request):
   return 'login'


def register(request):
   return 'register'


def error(request):
   return 'error'
对应关系(urls.py)

`from views import *
urls = (
   ('/index',index),
   ('/login',login),
   ('/register',register),
)
``

动静态页面

1.动态页面
页面上的数据不是全部写死的,有些是动态获取(后端传入)
2.静态网页
页面上的数据直接写死的,要想改变只能修改源码。

3.实际需求
后端代码获取当前时间,然后让前端页面展示:
(1)字符串替换

def get_time(request):
   import time
   ctime = time.strftime('%Y-%m-%d %X')
   with open(r'html_get_time.html','r',encoding='utf8')as f:
       data = f.read()
   # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换)
   data = data.replace('lalala',ctime)
   return data

(2)将字典数据传递给html页面并且想要在页面上操作字典数据;

def get_dict(request):
   user_dict = {'name':'jason','pwd':123,'hobby':['read','run','music']}
   with open(r'html_get_dict.html','r',encoding='utf8')as f:
       data = f.read()
   # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换)
   data = data.replace('hahaha',str(user_dict))
   return data

考虑到问题:我们无法自己实现在html页面上使用类似于后端的语法操作数据。所以引出jinja2模块。

jinja2模块

1.jinjia2说明
jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型。
2.jinja2下载

pip3 install jinja2

3.举个栗子——字典实现页面展示

views.py:

from jinja2 import Template
def get_dict(request):
   user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
   with open(r'templates/myhtml04.html','r',encoding='utf8') as f:
       data = f.read()
   temp = Template(data)
   res = temp.render(data=user_dict)  # 将字典传递给html页面 页面上通过>data即可获取(data仅仅是一个变量名)
   return res

start.py

from wsgiref.simple_server import make_server
from urls import urls
from views import *

def run(request, response):
   response('200 OK', [])
   target_path = request.get('PATH_INFO')  # /login
   func_name = None
   for url_tuple in urls:  # ('/index',index)    ('/login',login)
       if url_tuple[0] == target_path:
           func_name = url_tuple[1]  # 先存储匹配到的函数名
           break  # 一旦匹配到了内容立刻结束for循环
   # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上)
   if func_name:
       res = func_name(request)
   else:
       res = error(request)
   return [res.encode('utf8')]  # 作统一编码处理


if __name__ == '__main__':
  server = make_server('127.0.0.1', 8080, run)  # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用
  server.serve_forever()  # 永久启动

urls.py

from views import *
urls = (
   ('/get_dict',get_dict),
)

html_get_dict_html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"</script>
</head>
<body>
<h1>{{ data }}</h1>
<h1>{{ data['name'] }}</h1>
<h1>{{ data.get('pwd') }}</h1>
<h1>{{ data.hobby }}</h1>
</body>
</html>

请添加图片描述

模板语法

1.普通模板语法

<h1>{{ data }}</h1>
<h1>{{ data['name'] }}</h1>
<h1>{{ data.get('pwd') }}</h1>
<h1>{{ data.hobby }}</h1> 

2.for循环模板语法

{% for user in user_data %}
   <tr>
      <td>{{ user.id }}</td>
       <td>{{ user.name }}</td>
       <td>{{ user.age }}</td>
   </tr>
{% endfor %}

举个栗子:前端,后端,数据库三者数据联动

  • views.py文件
import pymysql
def get_mysql(request):
   conn =pymysql.connect(
       host='127.0.0.1',
       port=3306,
       user='root',
       password='000000',
       database='day55',
       charset='utf8',
       autocommit=True    # 做增删改操作时自动提交
   )
   cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
   sql = 'select * from userinfo'
   cursor.execute(sql)
  user_data = cursor.fetchall()
   with open(r'html_get_mysql.html','r',encoding='utf8')as f:
       data = f.read()
   temp = Template(data)
   res = temp.render(user_data=user_data)
   return res
   


==================补充知识点之pymysql连接数据库:==================
#创建数据库及表,然后插入数据
mysql> create database dbforpymysql;
mysql> create table userinfo(id int not null auto_increment primary key,username varchar(10),passwd varchar(10))engine=innodb default charset=utf8;
mysql> insert into userinfo(username,passwd) values('frank','123'),('rose','321'),('jeff',666);

#查看表内容
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
|  1 | frank    | 123    |
|  2 | rose     | 321    |
|  3 | jeff     | 666    |
+----+----------+--------+
3 rows in set (0.00 sec)
import pymysql

#连接数据库
db = pymysql.connect("localhost","root","LBLB1212@@","dbforpymysql")

#使用cursor()方法创建一个游标对象
cursor = db.cursor()

#使用execute()方法执行SQL语句
cursor.execute("SELECT * FROM userinfo")

#使用fetall()获取全部数据
data = cursor.fetchall()

#打印获取到的数据
print(data)

#关闭游标和数据库的连接
cursor.close()
db.close()

#运行结果
((1, 'frank', '123'), (2, 'rose', '321'), (3, 'jeff', '666'))
  • start.py文件
    如上面雷同
  • urls.py文件
from views import *
urls = (
   ('/get_mysql',get_mysql),
)
  • html_get_mysql,html文件
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
   <div class="container">
       <div class="row">
           <h1 class="text-center">数据展示</h1>
           <div class="col-md-6 col-md-offset-3"></div>
           <table class="table table-hover table-striped">
               <thead>
               <tr>
                   <th>主键</th>
                   <th>姓名</th>
                   <th>年龄</th>
               </tr>
               </thead>
               <tbody>
                   {% for user in user_data %}
                       <tr>
                           <td>{{user.id}}</td>
                           <td>{{user.name}}</td>
                           <td>{{user.age}}</td>
                       </tr>
                   {% endfor %}
               </tbody>
           </table>
       </div>
   </div>
</body>
</html>

请添加图片描述

python主流web框架

1.django框架
大而全,自身携带的功能非常多,类似于航空母舰。
缺陷:开发小项目的时候使用该框架有点笨重(大材小用)
2.flask框架
小而精,自身携带的功能非常少,类似于特种兵,主要依赖于第三方模块。
缺陷:受限于第三方模块的研发
3.tornado框架
异步非阻塞,该框架快到可以作为游戏服务器;
缺陷:上手难度是三者中最高的。
此外还有fastapi框架,sanic框架等

django框架简介

1.版本问题
(1)1.X(例如版本1.11):同步
(2)2.X(例如版本2.2):同步
(3)3.X(例如版本3.2):异步
请添加图片描述

2.启动注意事项
(1)计算机名称尽量不要有中文;
(2)项目中所有的py文件名尽量不要用中文;
(3)不同版本的python解释器配合不同版本的django,会出现一些报错,这种情况下可以仔细查找一下报错信息,里面会提示你是哪个py文件里面的代码出错,找到并把逗号删除。

152行:
widgets.py  

(4)一个pycharm窗口只允许有一个项目,不要做项目的嵌套。
3.验证django是否下载成功
cmd终端输入django-admin

django基本操作命令

在启动django项目的时候,一定要确保一个端口只有一个项目。
1.命令行操作

  • 创建django项目
django-admin startproject 项目名
  • 启动django项目

(1)先切换到项目目录下

cd 项目名

(2)执行启动目录

python38 manage.py runserver ip:port
  • 访问django服务端
    浏览器直接访问

  • 创建app应用

python38 manage.py startapp 应用名

说明:
django框架类似于是一个空壳子,给你提供所需的资源;
至于到底要写哪些功能,需要通过创建app来划分;
eg:eg:django初始项目可以看成是一所大学,app就相当于是大学里面的各个学院。

2.pycharm操作
鼠标操作即可。
请添加图片描述
如果遇到运行报错可以将setting.py文件中这行代码中/改为,即可!!!
请添加图片描述

3.命令行与pycharm操作的区别

  • 命令行不会自动创建templates文件夹
  • 命令行不会在配置文件编写关于templates文件夹的配置
'DIRS': [os.path.join(BASE_DIR, 'templates')]
  • pycharm自动创建的第一个应用会自动注册到配置文件中
'app01.apps.App01Config',
  • 针对db.sqlite3文件不用去在乎它有没有创建,只要运行了django会自动出来。

django目录结构

1.项目同名文件夹

文件名说明
init.py很少用,主要做一些冷门配置
settings.py项目配置文件
urls.py对应关系(目前简单的理解:网址后缀跟函数名)
wsgi.pydjango服务,基本不用
manage.pydjango入口文件
templates文件夹存储项目所需的html文件

2.应用名文件夹(可以有多个)

文件名说明
migrations文件夹orm相关(数据库打交道的记录)
init.py很少用,主要做一些冷门配置
admin.pydjango自带的后台管理
apps.py创建应用之后用于应用的注册
models.py存储与数据库表相关的类
tests.py自带的测试文件
views.py存储业务相关的逻辑代码(函数、类)
db.sqlite3自带的小型数据库

3.其他

文件名说明
urls.py路由层
views.py视图层
templates模板层
models.py模型层

django小白必会三板斧

  • HttpResponse
    主要用于直接返回字符串类型的数据
def index(request):
   return HttpResponse('你好啊,我是django2.2版本')
  • render
    主要用于返回html页面,并且支持模板语法
def func(request):
   return render(request, 'func.html')


=======同时也支持传值=============
def func(request):
   user_dict = {'name':'jason','pwd':123}
   return render(request, 'func.html',{'data':user_dict})
  • redirect
    主要用于页面重定向
def login(request):
# 针对别人的地址:
   return redirect('https://www.baidu.com')
# 针对自己的地址:
	return redirect('/index/')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值