Django简介


一、纯手撸web框架

# web框架可以简单的理解为基于互联网的web服务端

# 1.搭建一个基于互联网的一个服务端
    socket服务端
# 2.要遵循http协议
    四大特征
    数据格式
    想要状态码
# 3.然后根据网址的后缀名的不同请求不同的内容
# 4.请求格式
    GET
        向服务端索要数据
    POST
        向服务端提交数据
# 5.从请求数据中筛选出用户输入的网址后缀
target_url = data.decode('utf8').split(' ')[1]
'''
因为从客户端发送过来的数据里面有用户想要访问的后缀地址 然后这些数据又是字符串 又因为这些字符串空格居多 用户请求的后缀又在第一个空格后 所以可以按照空格分割 然后索引1提取
''' 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] # 可以提取出用户输入的地址 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') ''' 6.上述的代码有几个小问题: 1.每次编写web框架的时候都需要自己编写socket服务端(麻烦) 2.针对请求请求数据的处理复杂且重复 3.针对不同的网址后缀匹配方式代码冗余 '''

二、基于wsgiref撸web框架

# 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', [])  # 固定代码 
    target_path = request.get('PATH_INFO')  # 获取用户输入的后缀网址
    if target_path == '/index':
         return [b'index']
    elif target_path == '/login':
         return [b'login']
    else:
         return [b'404 not found!']

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

1.wsgiref模块解决了两个问题
    1.重复写socket代码
    2.针对请求数据格式的复杂且重复
2.但是对匹配后缀名的处理还是代码冗余
    我们可以把匹配后缀的名的代码封装一个一个函数
    def index():
        return ('index')
    def func():
        return('func')
    def login():
        return('login')
    # 然后按照字符串和函数的对应关系写到元祖中
    urls = (('/index',index),('/func',func),('/login',login))
    然后通过循环取出字符串匹配 如果匹配上就返回函数里的内容

def run(request, response):
    """
    :param request: 请求数据
    :param response: 响应数据
    :return: 返回给客户端的数据
    """
    response('200 OK', [])  # 固定代码 无需掌握
    # print(request)  # 自动将请求数据全部处理成字典k:v键值对形式
    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()  # 永久启动


# 3.在根据功能的不同 把代码封装到不同的py文件中
# urls文件中放 函数与后缀名的对应关系
urls = (('/index',index),('/func',func),('/login',login))

# views.py文件中放函数代码 写功能
    def index(request):  # 还可以根据数据的请求内容返回给函数 利于后续扩展的方便
        return ('index')
    def func(request):
        return('func')
    def login(request):
        return('login')

# 然后基于wsgiref编写的代码就是服务端就可以不用改了
def run(request, response):
    """
    :param request: 请求数据
    :param response: 响应数据
    :return: 返回给客户端的数据
    """
    response('200 OK', [])  # 固定代码 无需掌握
    # print(request)  # 自动将请求数据全部处理成字典k:v键值对形式
    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 对应关系
views.py 功能函数
start.py 启动文件
templates文件夹 存储html

三、动静态网页

'''
静态网页
  静态网页上的数据是直接写死 是不会变的
动态网页
  数据是实时获取的  可以实时变化的
  eg:
      1.后端获取当前时间展示到html页面上
      2.数据是从数据库中获取的展示到html页面上
'''

# 1.制作动态网页
'''在后端获取时间上传到后端页面'''
import datetime
def get_time(request):
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
    # 怎么把将后端获取到的数据"传递"给html文件?
    with open(r'templates/03 mytime.html', 'r', encoding='utf8')as f:  # 通过读取文件操作 读取html文件 
# 可以把body标签中的标签替换成我们获取到的时间即可
        data = f.read()
        # data就是一堆字符串
        data = data.replace('dsadad', current_time)  # 在后端将html叶念处理好之后再返回给前端
        return data

# 2.将字典传到前端页面
def get_dict(request):
    user_dict = {'username': 'jason', 'age': 18, 'hobby': 'run'}
    with open(r'templates/04 get_dict.html', 'r', encoding='utf8') as f:
        data = f.read()
        data = data.replace('dsadad', current_time) 
        return data  
# 但是这个时候只是字符串 如果在html页面上想用字典的值该怎么办?

四、jinja2模块

# jinja2模块是第三方模块需要下载
    pip3 install jinja2

# 1.使用
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页面上就可以使用jinjia2模块语法使用字典里的值了
<h1>{{ data }}</h1>  #  {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
<h1>{{ data['name'] }}</h1>  # jason
<h1>{{ data.get('pwd') }}</h1>  # 123
<h1>{{ data.hobby }}</h1>  # ['read', 'run', 'music']

# jinja2模块还可以使用for循环(一般python语法jinja2在前端都可以使用)
{% for user in data %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
    </tr>
{% endfor %}

# 这个时候就可以使用django框架将数据库和前端交互起来了
    # 我们可以先在数据库中创建一些数据
    # 然后通过pymysql获取数据库中数据
    # 然后html通过jinja2模板语法获取数据
# 后端页面
import pymysql
from jinja2 import Template
def get_mysql(request):
     conn = pymysql.connect(
            host = '127.0.0.1',
            port = 3306,
            user='root',
            password='',
            database='db5',
            charset='utf8',
            autocommit=True,)
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from userinfo'
    cursor.execute(sql)
    user_data = cursor.fetchall()  # user_data就是数据库中的数据
    with open(r'templates/myhtml.html','r',encoding='utf8') as f:  # 打开前端页面
        data = f.read()
    temp = Template(data)  # 将前端页面传入jinja2对象
    res = temp.render(user =user_data)  # 前端就可以通过user获取数据
    return res
# 前端页面
<p>{{ user }}</p>
<p>{{ user.name }}</p>

五、python主流的web框架

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

fastapi框架、sanic框架、...
    最近流行的 抽空可以看看
 
"""
框架虽然多 但是内部逻辑大差不差 我们重点学习一个即可>>>:django
    如果你是小白切记不要同时学习上述框架
"""

六、django框架简介

# 1.版本问题
django3.X:默认支持异步功能
django2.X:默认不支持异步
django1.X:默认不支持异步

# 2.启动注意事项
    1.计算机名称尽量不要有中文
     2.项目中所有的py文件名尽量不要用中文
     3.不同版本的python解释器配合不同版本的django 会有一些报错
        仔细查找一下报错信息 里面会提示你是哪个py文件里面的代码出错
       找到那一行代码 把逗号删除即可
            widgets.py  152  
      4.一个pycharm窗口只允许有一个项目 不要做项目的嵌套
# 3.下载
    pip3 install django==版本

七、基本使用

1.命令行创建django项目

# 1.验证django下载是否成功
    在终端输入django-admin 有反应就是成功

# 2.命令行操作
        1.创建django项目
            django-admin startproject 项目名
        2.启动django项目
            1.先切换到项目名下
                cd 项目名
            2.输入启动命令
                python3 manage.py runserver IP:PORT
# 3.访问django项目
    直接在浏览器访问即可 在浏览器输入 IP:PORT
4.创建app应用
        """
        django框架类似于是一个空壳子 给你提供所需的资源
        至于到底要写哪些功能 需要通过创建app来划分
            eg:django初始项目可以看成是一所大学
               app就相当于是大学里面的各个学院
        """
        python3 manage.py startapp 应用名

2.pycharm创建django项目

# 1.pycharm操作django
    1.new project
      选择django 填写应用即可
    '''pycharm默认会自动帮你创建模板文件夹 并提供创建一个app的功能'''
  2.创建更多的app
      tools
        run manage.py task 命令自动提示
        # 创建好app之后还要取配置文件添加
        INSTALLED_APPS = ['应用名']
  3.启动项目
      直接点击绿色箭头 
      还可以修改端口号 edit configurations   
"""
在启动django项目的时候 一定要确保一个端口只有一个项目
""" 

 八、命令行与pycharm的区别

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

九、django目录结构

django项目目录
    项目同名文件夹
        __init__.py         很少用 主要做一些冷门配置
       settings.py           项目配置文件
       urls.py                 对应关系(目前简单的理解:网址后缀跟函数名)
       wsgi.py                django服务 基本不用

   manage.py                django入口文件
   templates文件夹          存储项目所需的html文件

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

   db.sqlite3               自带的小型数据库

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

十、小白必会三板斧

1.HttpResponse

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

 

 2.render

# 主要用于返回html页面 支持模板语法

 

 3.redirect

# 重定向
        就是当我们访问一个网址的时候却跳到了另一个网址
        可以写其他网址
        也可以写自己的网址

 

 

 十一、作业

1.使用django展示MySQL数据到前端页面

数据库内容:
+----+---------+------+
| id | name    | age  |
+----+---------+------+
|  1 | jason   |   18 |
|  2 | kevin   |   28 |
|  3 | tony    |   38 |
|  4 | oscar   |   48 |
|  5 | jerry   |   26 |
|  6 | stephen |   20 |
+----+---------+------+

1.url(路由层)

url(r'^get_mysql', views.get_mysql)

2.views(视图层)

import pymysql


# Create your views here.


def get_mysql(request):
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='',
        database='db12',
        charset='utf8',
        autocommit=True
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from userinfo'
    cursor.execute(sql)
    user_data = cursor.fetchall()
    return render(request, 'get_mysql.html', {'user_data': user_data})

3.templates(模板层)

<div class="container">
    <h1 class="text-center">数据展示</h1>
        <table class="table table-striped table-hover">
            <thead>
                <tr>
                    <th>id</th>
                    <th>姓名</th>
                    <th>年龄</th>
                </tr>
            </thead>
            <tbody>

                {% for user_obj in user_data %}
                    <tr>
                        <td>{{ user_obj.id }}</td>
                        <td>{{ user_obj.name }}</td>
                        <td>{{ user_obj.age }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
</div>

 

posted @ 2022-08-30 17:46  stephen_hao  阅读(93)  评论(0编辑  收藏  举报