Django

今日内总结

  • 纯手撸web框架
1.socket代码
2.http数据格式
3.分支结构匹配路由
  • 基于wsgiref模块
封装了socket及http数据格式处理
  • 框架代码优化处理
面条版 函数版 模块板 面向对象版

urls.py    路由层
views.py   视图层
templates  模板层
  • jinjia2模块语法
能够在html文件内使用类似于后端的代码处理数据
  • 动静态网页
核心就在于网页上的数据
  • 动态展示数据库数据
pymysql jinja2
  • 简易web框架请求流程图
  • python主流web框架
django、flask、tornado、fastapi、sanic
  • django简介
一些默认端口号
    mysql:3306
    django:8000
    redis:6379
    mogodb:27107
    flask:5000
    Tomcat:8080
1.版本问题
2.报错问题
3.操作命令
    django-admin startproject 项目名
    cd 项目名
    python manage.py runserver ip:port
    python manage.py startapp 应用名
"""
1.temlates文件夹创建
2.templates配置信息
    ‘DIR’:[os.path.join(BASE_DIR,'templates')]
"""
  • django目录结构
项目目录
    同名目录
        settings.py        
        urls.py
    manage.py    入口文件
    db.sqlite3    自带的数据库
    应用名
        migrations文件夹
        admin.py
        views.py
        models.py
    templates文件夹
  • django小白必会三板斧
HttpResponse
render
redirect

附加知识点:

  重定向:

301:永久重定向,表示请求的资源分配了新的url,以后应使用新url

302:临时重定向,请求的资源临时分配了新的url(response中location所指的地址),本次请求暂时使用新url

  服务器返回302时,也会返回location,浏览器再次请求location中指定的地址,也就是浏览器请求了2次
   
304:自从上次请求过后,网页未被修改过。客户端发送请求,有缓存则返回304,客户端使用缓存资源

 

今日内容详细

一、Web框架本质

  web框架本质上可以看成是一个功能强大的socket服务端,用户的浏览器可以看成是拥有可视化界面的socket客户端。两者通过网络请求实现数据交互,也可以从架构层面上先简单的将Web框架看作是对前端、数据库的全方位整合。

  web框架可以简单的理解为是基于互联网的web服务端>>>:socket服务端      

二、纯手撸web框架

  编写一个简易的web框架:

  ①socket服务端代码

  ②HTTP协议

  ③根据网址后缀的不同请求不同的内容

  ④请求方式

    GET

      朝服务段索要数据

    POST

      朝服务端提交数据

  ⑤从请求数据格式中筛选出用户输入的网址后缀

      target_url = data.decode('utf8').split('')[1]

1.搭建socket服务端

import socket


server = socket.socket()
server.bind(('127.0.0.1', 8082))
server.listen(5)


while True:
    sock, addr = server.accept()
    data = sock.recv(1024)
    sock.send(b'Today is a good day')

     

 

2.浏览器发送请求

# 服务端响应的数据需要符合HTTP响应格式
sock.send(b'HTTP1.1 200 OK\r\n\r\nToday is a good day')

--- data里面都是请求返回的数据

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')
    elif target_url == '/login':
        sock.send(b'login view')
    elif target_url == '/reg':
        sock.send(b'reg view')
    else:
        sock.send(b'404 error')

 

 

4.总结

 纯手撸框架的缺陷:

  ①socket代码过于重复(每次搭建服务端都需要反复造轮子)

  ②针对HTTP请求数据没有完善的处理方式(目前只是定向切割)

三、基于wsgiref模块撸

 ps:wsgiref是内置模块,wsgiref内部封装了socket代码和对请求数据的处理,wsgiref是很多python底层web框架的模块;wsgiref识别到代码框架内的代码进行了修改,会自动重启

1.代码实操

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

def run(request, response):
    """
    :param request: 请求数据
    :param response: 响应数据
    :return: 返回给客户端的数据
    """
    response('200 OK', [])  # 固定代码 无需掌握
    # 是request 自动将请求数据全部处理成字典k:v键值对形式
    # print(request)  # (打印出来的是k:v键值对形式的大字典)
    target_path = request.get('PATH_INFO')  # /login
    # if target_path == '/index':
    #     return [b'index']
    # elif target_path == '/login':
    #     return [b'login']
    # else:
    #     return [b'404 not found!']
    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()  # 永久启动

 大字典:

2.wsgiref模块解决了两个问题

  ①socket代码重复编写造轮子

  ②针对请求数据格式的处理复杂且重复

 3.思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)

   先从大字典中查找出记录网址后缀的键值对

  1.不推荐使用连续的多个if判断

  2.针对面条版的代码首先应该考虑封装成函数

 4.根据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):
    """
    :param request: 请求数据
    :param response: 响应数据
    :return: 返回给客户端的数据
    """
    response('200 OK', [])  # 固定代码 无需掌握
    # print(request)  # 自动将请求数据全部处理成字典k:v键值对形式
    target_path = request.get('PATH_INFO')  # /login    获取用户输入的后缀
    # if target_path == '/index':
    #     return [b'index']
    # elif target_path == '/login':
    #     return [b'login']
    # else:
    #     return [b'404 not found!']
    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 = (
    ('/home', home),
    ('/index', index),
    ('/login', login),
    ('/register', register),
    ('/func',func)
)

③views.py

def index(request):
    return 'index'


def login(request):
    return 'login'


def register(request):
    return 'register'


def error(request):
    return '404 error'

④templates文件夹

5.总结

  拆分后的好处在于要真想增加一个功能,只需要在views.py中编写函数,urls.py中添加对应关系即可

6.框架请求流程

7.主要关键字

  ①urls.py

    后缀与函数名对应关系

    ('/index',register)

      后缀专业名词称之为'路由'

      函数名专业名词称之为'视图函数'

      urls.py专业名词称之为'路由层'

  ②views.py

    专门编写业务逻辑代码

    可以是函数  也可以是类

    函数专业名词称之为‘视图函数’

    业名词称之为‘视图类’

    views.py专业名词称之为‘视图层’

  ③templates文件夹

    专门存储html文件

    html文件专业名词称之为‘模板文件’

    templates文件夹专业名词称之为‘模板层’

四、动静态网页

1.动态网页

  页面上的数据不是全部写死的,有些是动态获取(从后端传入)

2.静态页面

  页面上的数据直接写死的,要想改变只能修改源码

3.(动态网页)实际需求

  ①后端代码获取当前时间,然后让前端页面展示

    可以使用字符串替换的方法

-------首先是前端html页面------

-------后端用字符串替换的方式,把当前时间展示到前端页面上,完成动态页面-------

 

  ②将字典数据传递给html页面并且想要在页面上操作字典数据

    我们无法自己实现>>>:在html页面上使用类似于后端的语法操作数据

    但是有个模块可以做到👇

【作为一名工程师,你要时刻知道,当你想完成一个功能但实现不了,那么想想有没有别人能做到,也就是有没有模块可以做到】

五、jinja2模块(第三方模块)

1.功能

  jinja2能够让我们在html文件内使用类似于后端的语法来操作做各种数据类型,jinjia2打通了前后端的操作

    那么jinja2好处在哪里呢?

      比如说如果你以后写前后端结合的项目,Jinja2会让你写代码非常非常的方便,因为语法差不多。

      

2.下载模块

    pip3 install jinja2
  pip3 install jinja2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

3.代码实操

-------后端操作--------

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

------前端html页面操作-------

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

 

jinja2只有在全栈(前后端不分离)才有可能用到,如果前后端是分离的,那么模板语法你是用不到的

六、模块语法 (连接上一个问题:将字典数据传递给html页面并且想要在页面上操作字典数据)

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

# jinjia2的for循环
{% for user in user_data %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
    </tr>
{% endfor %}

❓注意:python操作数据库是需要用到一个模块的---->pymysql【这里涉及到pymysql写了一段代码,但是我不懂什么意思,想不起来pymysql这里的知识点是在哪里讲的】

 

七、python主流web框架

1.django框架

优点:大而全,自身携带的功能非常的多,类似于航空母舰

  缺陷: 开发小项目的时候使用该框架有点笨重(大材小用)

2.flask框架

  优点:小而精,自身携带的功能非常的少,类似于特种兵,主要依赖于第三方模块(第三方模块强我就强,第三方模块弱我就弱)

  缺点:受限于第三方模块的开发

3.tornado框架

 优点:异步非阻塞,该框架快到可以作为游戏服务器

  缺点:上手难度是三者最高的

4.fastapi框架、sanic框架、...

 最近流行的 抽空看看

‘’

  to   c   面向客户(就是我这个软件开发出来是要挣钱的,比如说淘宝,天猫,拼多多)

  to   b  就是比如说内部公司里面的一些管理软件,这个不是让用户去消费的,是让用户去管理东西的 

ps:to b 更赚钱

‘’

ps:框架虽然多,但是内部逻辑大差不差

八、django框架简介

1.版本问题

  1.X:同步  1.11          同步:提交任务在原地等待

  2.X:同步  2.2

  3.X:异步  3.2

ps:无论用什么版本都可以,区别不大    2.2  (LTS就是官方维护的版本)  

2.启动注意事项

  ①计算机名称尽量不要有中文

  ②项目中所有的py文件名尽量不要用中文

  ③不同版本的python解释器配合不同版本的django 会有一些报错

    仔细查找一下报错信息,里面会提示你是哪个py文件里面的

代码出错:

  找到那一行代码,把逗号删除即可

     widgets.py     152

  ④一个pycharm窗口只允许有一个项目,不要做项目的嵌套(嵌套可能导致项目跑不起来

3.下载django

4.验证django是否下载成功

  cmd终端输入django-admin   【有反应就成功了,没反应就没成功】

 

九、django基本命令操作

1.命令行操作

  ①创建django项目

    django-admin startproject   项目名(想怎么起怎么起)

  ②启动django项目

    1.先切换到项目根目录下

      cd  项目名

    2.执行启动目录

      python38 manage.py runserver ip:port

 8000是django默认的端口号

  ③访问django服务端

    浏览器直接访问

  ④创建app应用

    django框架类似于是一个空壳子,给你提供所需的资源

    至于到底要写哪些功能,需要通过创建app来划分

      eg:django初始项目可以看成是一所大学

        app就相当于是大学里面的各个学院

    python38 manage.py startapp 应用名(尽量表达出功能的应用名)

2.pycharm操作

鼠标点点点即可

    在启动django项目的时候,一定要确保一个端口只有一个项目

------pycharm创建django项目------

--------如果django版本和pycharm版本不适配,报错需要修改的地方-------

------运行之后,浏览器查看------

------想要项目跑在其他端口上-----

 

十、命令行与pycharm操作的区别

  1.命令行不会自动创建templates文件夹

  2.命令行不会在配置文件编写关于templates文件夹的配置

  ps:如果将来手动创建django项目的话,首先就要去配置文件中配置DIRS

  3.pycharm自动创建的第一个应用会自动注册到配置文件中,但是命令行的需要手敲

    ps:这里创建应用配置的意思就是将应用开辟到django这个项目中来

  4.针对db.sqlite3文件不用去在乎他有没有创建,只要运行了django会自动跳出来(无论是命令行还是pycharm都会自动创建db.sqlite3)

十一、django目录结构

1.django项目目录

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

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

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

 

urls.py 路由层
views.py 视图层
templates 模板层
models.py 模型层

十二、django小白必会三板斧

1.HttpResponse

 主要用于直接返回字符串类型的数据

2.render

  主要用于返回html页面,并且支持模板语法

3.redirect

  主要用于页面重定向

 

posted @ 2022-08-30 22:28  W-Y-N  阅读(149)  评论(0)    收藏  举报