手撸web框架即引入框架思想,wsgierf模块,动静态网页,模板语法jinja2,python三大主流web框架,django安装,三板斧

手撸web框架

web框架

什么是web框架? 暂时可理解为服务端。

软件开发架构

  • C/S架构
  • B/S架构
# 后端
import socket

server = socket.socket()  # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8000))  # IP协议,以太网协议,arp协议...
server.listen(5)  # 监听,池的概念...

while True:
    conn, addr = server.accept()
    data = conn.recv(1024)
    conn.send(b'hello word')
    conn.close()

image

HTTP协议

"""
HTTP协议:     数据传输是明文
HTTPS协议:	  数据传输是密文
websocket协议:数据传输是密文
"""

HTTP四大特性

  • 基于请求响应
  • 基于TCP、IP作用于应用层之上的协议
  • 无状态
  • 短/无连接

HTTP数据格式

  • 请求首行
  • 请求头
  • 请求体

HTTP响应状态吗

  • 1xx
  • 2xx : 200
  • 3xx : 重定向
  • 4xx : 403,404
  • 5xx : 500

基于上述大致回顾,得出结论,代码没有遵循HTTP协议,加入HTTP相关参数。

# 后端
import socket

server = socket.socket()  # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8000))  # IP协议,以太网协议,arp协议...
server.listen(5)  # 监听,池的概念...

while True:
    conn, addr = server.accept()
    data = conn.recv(1024)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
    conn.close()

image

image

深入解析客户端返回数据,此时提出一个需求,要用在客户端输入127.0.0.1:8000/index时浏览器页面返回不再是hello world,而是输入的后缀名,如:index。

思路:拿到用户输入的后缀,用其做判断。

上图红框中显示的是所有请求头相关的信息。

image

# 用户客户端输入的后缀在第一个斜杠后方显示。
b'GET / HTTP/1.1\r\n
# 后端
import socket

server = socket.socket()  # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001))  # IP协议,以太网协议,arp协议...
server.listen(5)  # 监听,池的概念...

"""
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8000\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "macOS"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: 
"""


while True:
    conn, addr = server.accept()
    data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
    data = data.decode('utf8') # 此时,data为字符串类型
    print(type(data))
    conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
    conn.close()
    
输出:
<class 'str'>

那么,如何获取字符串中特定的内容?

  • 正则

  • 若字符串有规律可以使用切割。

我们注意到字符串开头均头空格,先试用spilt(' ')切割空格

while True:
    conn, addr = server.accept()
    data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
    data = data.decode('utf8') # 此时,data为字符串类型
    res = data.spilt(' ')
    print(res)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
    conn.close()

image

想要的元素为列表的第二个,索引为[1]的位置,那么如何获取列表中索引为[1]的元素即用户输入的url后缀?显而易见了。

while True:
    conn, addr = server.accept()
    data = conn.recv(1024)  # 由于此时的data为二进制数据类型,需要先转字符类型
    data = data.decode('utf8')  # 此时,data为字符串类型
    current_path = data.split(' ')[1] # 获取用户输入的网址后缀
    print(current_path)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
    conn.close()

image

加入判断,使用用户输入不同后缀,返回不同内容:

# 后端
import socket

server = socket.socket()  # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001))  # IP协议,以太网协议,arp协议...
server.listen(5)  # 监听,池的概念...

"""
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8000\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "macOS"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: 
"""

while True:
    conn, addr = server.accept()
    data = conn.recv(1024)  # 由于此时的data为二进制数据类型,需要先转字符类型
    data = data.decode('utf8')  # 此时,data为字符串类型
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 基于HTTP为流式协议
    current_path = data.split(' ')[1]  # 获取用户输入的网址后缀
    if current_path == '/index':
        conn.send(b'index')
    elif current_path == '/login':
        conn.send(b'login')
    else:
        conn.send(b'hello word')
    conn.close()

image

既然可以返回不同的内容,那么可否能返回不用页面???

# 后端
import socket

server = socket.socket()  # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001))  # IP协议,以太网协议,arp协议...
server.listen(5)  # 监听,池的概念...

"""
防止代码看来冗余,删除
"""
while True:
    conn, addr = server.accept()
    data = conn.recv(1024)  # 由于此时的data为二进制数据类型,需要先转字符类型
    data = data.decode('utf8')  # 此时,data为字符串类型
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    current_path = data.split(' ')[1]  # 获取用户输入的网址后缀
    if current_path == '/index':
        # conn.send(b'index')
        with open(r'myhtml.html','rb') as f:
            conn.send(f.read())
    elif current_path == '/login':
        conn.send(b'login')
    else:
        conn.send(b'hello word')
    conn.close()

image

纯手撸web框架不足之处:

  • 代码重复
  • 手动处理HTTP格式数据,只能拿到URL后缀信息,其他数据获取繁琐(数据格式一样处理的代码也大致相同,重复写代码)。
  • 未解决并发问题

借助于wsgiref模块

from wsgiref.simple_server import make_server

def run():
    pass

if __name__ == '__main__':
    make_server()

control+鼠标左键点击make_server():

def make_server(
    host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
):
    """Create a new WSGI server listening on `host` and `port` for `app`"""
    server = server_class((host, port), handler_class)
    server.set_app(app)
    return server
# host : 服务端IP,port : 服务端端口 app : ?

编写wsgiref

from wsgiref.simple_server import make_server


# 再给run函数加括号调用时加两个形参
def run(env,response):
    """

    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    print(env)


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever() # 启动服务端
    """
    将实时监听127.0.0.1:8080地址,只要有客户端链接,
    都会交给run函数处理即为(加括号触发run函数的运行)
    """

image

报错的原因是代码未写全。

from wsgiref.simple_server import make_server


# 再给run函数加括号调用时加两个形参
def run(env,response):
    """

    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    print(env)
    response('200 OK',[]) # 返回数据,响应首行,响应头
    return [b'hello wsgiref']


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever() # 启动服务端
    """
    将实时监听127.0.0.1:8080地址,只要有客户端链接,
    都会交给run函数处理即为(加括号触发run函数的运行)
    """

image

此时用户后缀无论写什么都会触发run方法,验证了只要有客户端链接,发送请求,都会交给run函数处理即为(加括号触发run函数的运行)。

抛出请求,无论客户输入什么,浏览器页面都返回用户输入。

思路,找到用户输入返回的键

image

代码:

from wsgiref.simple_server import make_server


# 再给run函数加括号调用时加两个形参
def run(env, response):
    """

    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    response('200 OK', [])  # 返回数据,响应首行,响应头
    current_path = env.get('PATH_INFO')  # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
    if current_path == '/index':
        return [b'index']
    elif current_path == '/login':
        return [b'login']
    else:  # 如果后缀找不到,弹出404页面,即针对404页面也可以做响应的处理
        return [b'404 error']


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()  # 启动服务端
    """
    将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
    都会交给run函数处理即为(加括号触发run函数的运行)
    """

image

纯手撸和wsgiref对比:

image

wsgiref只需要写业务逻辑和获取数据。

如果有成百上千的后缀难道要写成丢的elif?

from wsgiref.simple_server import make_server


def index():
    return 'index'


def login():
    return 'login'													'三个函数'


def error():
    return '404 error'


# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
urls = [
    ('/index', index),											'对应关系'
    ('/login', login)
]


# 再给run函数加括号调用时加两个形参						
																							'匹配关系'
def run(env, response):
    """

    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    response('200 OK', [])  # 返回数据,响应首行,响应头
    current_path = env.get('PATH_INFO')  # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
    # 提前定义一个变量,存储匹配到的函数名
    func = None
    for url in urls:  # 此时的url是一个个元祖()
        if current_path == url[0]:
            # 将url对应的函数名赋值给func
            func = url[1]
            break  # 匹配到一个后 立刻结束for循环
    # 也有可能for循环结束后func依旧为None
    if func:
        res = func()
    else:
        res = error()
    # 统一封装,编码
    return [res.encode('utf-8')]


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()  # 启动服务端
    """
    将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
    都会交给run函数处理即为(加括号触发run函数的运行)
    """

再给函数传参,env,是否就意味着可以拿到 客户端返回的数据,并在此基础之上做处理。并且若要添加功能需要在index,login,error三个函数中操作即可,但是代码层面来讲太过冗余且杂乱。

安装不同的功能拆成不同的py文件

  • urls.py
  • views.py

匹配关系:

基于wsgiref.py

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



# 再给run函数加括号调用时加两个形参
def run(env, response):
    """

    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    response('200 OK', [])  # 返回数据,响应首行,响应头
    current_path = env.get('PATH_INFO')  # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
    # 提前定义一个变量,存储匹配到的函数名
    func = None
    for url in urls:  # 此时的url是一个个元祖()
        if current_path == url[0]:
            # 将url对应的函数名赋值给func
            func = url[1]
            break  # 匹配到一个后 立刻结束for循环
    # 也有可能for循环结束后func依旧为None
    if func:
        res = func(env)
    else:
        res = error(env)
    # 统一封装,编码
    return [res.encode('utf-8')]


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()  # 启动服务端
    """
    将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
    都会交给run函数处理即为(加括号触发run函数的运行)
    """

urls.py :对应关系

# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
# url 与 函数的对应关系
from views import *


urls = [
    ('/index', index),
    ('/login', login)
]

views.py:业务逻辑

# 业务逻辑

def index(env):
    return 'index'


def login(env):
    return 'login'


def error(env):
    return '404 error'

测试:

正常

现在如果客户要增加一个后缀xxx,要求浏览器返回xxx,只需要修改urls和views即可。

urls

urls = [
    ('/index', index),
    ('/login', login),
    ('/xxx', xxx)
]

views.py

# 业务逻辑

def index(env):
    return 'index'


def login(env):
    return 'login'


def error(env):
    return '404 error'
  
def xxx(env):
    return 'xxx'

那么如果需要创建多个HTML呢?难道Pycharm的左侧要出现N个HTML文件?可以创一个文件夹存放。

templates

将所有的HTML文件都防止与templates中

测试,只需要变动views.py 即可

新创建一个HTML文件。

myxxx.html

<body>
<h1>一剑霜寒十四州</h1>
</body>

views.py

def xxx(env):
    with open(r'templates/myxxx.html','r',encoding='utf8') as f:
        return f.read()

image

借助于wsgiref模块

根据功能的不同,划分不同的文件和文件夹。

  • urls.py >>> 路由(指URL后缀:http://127.0.0.1:8080/xxx)与视图函数(也是函数,处理业务逻辑的)对应关系
  • views.py >>> 存放视图函数(后端业务逻辑)
  • templates >>> 存放HTML文件

安装功能的不同拆分后,后续添加功能只需要在urls.py书写对应关系然后去views.py书写业务逻辑即可。

动静态网页

  • 静态网页
    页面上的数据写死,亘古不变
  • 动态网页
    数据实时获取:
    1.后端获取当前时间,展示到HTML
    2.数据从数据库中获取展示到HTML页面

动态网页制作:后端获取当前时间,展示到HTML

views.py

import datetime
def get_time(env):
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
    # 如何将后端获取到的数据"传递"给html文件?
    with open(r'templates/mytime.html','r',encoding='utf8') as f:
        data = f.read()
        # data就是以对字符串
    data = data.replace('asdasdad',current_time) # 在后端将html页面处理好之后再返回前端
    return data

urls.py

urls = [
    ('/index', index),
    ('/login', login),
    ('/xxx', xxx),
    ('/get_time',get_time)
]

mytime.html

<body>
asdasdad
</body>

image

如何将一个字典传递给html文件,并且可以在文件上方便快捷的操作字典数据

模板语法值jinja2模块

安装:

pip3 install jinja2

views.py

from jinja2 import Template
def get_dict(env):
    user_dic = {'username':'junjie','age':18,'hobby':'play'}
    with open(r'templates/get_dict.html','r',encoding='utf8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user=user_dic)
    # 给get_dict.html传递了一个值 页面上通过变量名user就能拿到user_dict
    return res

urls.py

from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/xxx', xxx),
    ('/get_time', get_time),
    ('/get_dict', get_dict)
]

get_dict.html

<body>
<h1>我是一个页面</h1>
{{ user }}
</body>

jinja2 html 的字典取值方式 : jinja2的模板语法

只在后端起作用

get_dict.html

<body>
<h1>我是一个页面</h1>
{{ user }} <!--获取到后端的传值-->
{{ user.get('username')}}
{{ user.age }}
{{ user['hobby'] }}
</body>

image

后端获取数据库中数据展示到前端页面

访问一个url,后端前往数据库拿数据,通过jinja2模板语法传到页面,再发给浏览器渲染。

urls.py

# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
# url 与 函数的对应关系
from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/xxx', xxx),
    ('/get_time', get_time),
    ('/get_dict', get_dict),
    ('/get_user', get_user)
]

终端mysql创建库,表,并存入数据。

mysql> create database day59;
mysql> create table userinfo(id int primary key auto_increment,username varchar(16),password int,hobby varchar(16));
mysql>  insert into userinfo(username,password,hobby) values('jason',123,'study'),('junjie',321,'play'),('tony',111,'生蚝'),('tom',222,'丝袜');
mysql> select * from userinfo;
+----+----------+----------+--------+
| id | username | password | hobby  |
+----+----------+----------+--------+
|  1 | jason    |      123 | study  |
|  2 | junjie   |      321 | play   |
|  3 | tony     |      111 | 生蚝   |
|  4 | tom      |      222 | 丝袜   |
+----+----------+----------+--------+
4 rows in set (0.00 sec)

views.py

import pymysql
def get_user(env):
    # 前往数据库中获取数据 传递给html页面,借助于模板语法 发送给浏览器
    conn = pymysql.connect(
        host= '127.0.0.1',
        port= 3306,
        user='root',
        password='xJNN0315',
        db='day59',
        charset='utf8',
        autocommit=True # 自动提交
    )
    # 字典格式
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from userinfo'
    affect_rows = cursor.execute(sql)
    data_list = cursor.fetchall() # 输出格式: [{},{},{}]
    # 将获取到的数据传递给html文件
    with open(r'templates/get_data.html','r',encoding='utf8')as f:
        data = f.read()
        tmp = Template(data)
        res = tmp.render(user_list=data_list) # user_list 变量名想取什么都行
        return res

get_data.html

<body>
{{ user_list }}
</body>

image

如何将这一个个数据放到html文件中?并以表格的形式展示?

get_data.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>
<!--模板语法同样支持for循环-->
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">用户数据</h1>
            <table class="table table-hover table-striped">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>username</th>
                        <th>password</th>
                        <th>hobby</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_dict in user_list %}
                        <tr>
                            <td>{{ user_dict.id }}</td>
                            <td>{{ user_dict.username }}</td>
                            <td>{{ user_dict.password }}</td>
                            <td>{{ user_dict.hobby }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

</body>
</html>

image

此时页面就属于动态页面,数据库增,该,删,全部互联,页面刷新即可。

自定义简易版本web框架请求流程图

wsgiref 模块做了两件事
1.请求来的时候解析http格式的数据,封装成大字典
2.响应走的时候给数据打包成符合http格式 再返回给浏览器

python三大主流web框架

  • Django
  • flask
  • tornado

Django

特点:大而全,自带功能特别特别特别多。

不足:有时,过于笨重。

flask

特点:小而精,自带的功能特别特别特别少,第三方模块特别特别特别的多,如果将flask第三方的模块加起来完全可以飞过Django,并且也越来越像Django。

不足:较于依赖第三方的开发者,兼容性问题

tornado

特点:异步非阻塞,支持高并发,可以开发游戏服务器。

不足:当前而言不足暂时我不会。

web框架可以分成三个部分

A : socket部分

B : 路由与视图函数对应关系(路由匹配)

C : 模板语法

Django

A : 用的wsgiref

B : 自身

C : 自身

flask

A : 用的wekzeug,内部还是wsgierf

B : 自身

C : 用的jinja2

tornado

A : 自身

B : 自身

C : 自身

注意事项

想要电脑正常运行django项目必须满足以下三个条件。

  • 1.计算机的名称不能含有中文
  • 2.一个python窗口只开一个项目
  • 3.项目中所有文件也尽量不要含有中文
  • Python解释器尽量使用3.4~3.6之间
    (如果项目报错,点击最后一个报错信息,去源码中把逗号删掉)

Django版本问题

  • 1.x
  • 2.x
  • 3.x

release-roadmap.3c7ece4f31b3

公司之前用的1.8,慢慢过渡到1.11版本,有些项目使用到了2.0

Django官网:https://www.djangoproject.com/download/

Django安装

pip3 install jango==1.11.11
# 检测是否安装成功
django-admin

若已安装其他版本,无需自己卸载,直接重新安装,会自动卸载原有版本

django基本操作

  • 命令行操作
  • pycharm操作

命令行

创建django项目

django-admin startproject 项目名

django应用

Django是一款专门用来开发app的web框架

Django 框架就类似于一所大学,app就类似大学里面各个学院,一个app就是一个独立模块。

如开发淘宝:
	订单相关
  用户相关
  投诉相关
  ..功能模块
  一个app对应不同的功能

主要文件介绍:

-mysite文件夹 : 自定义Django项目名
	--mysite : 文件夹
    ---settings.py : 项目的配置文件
    ---urls.py     : 路由与视图函数的对应关系(路由层)
    ---wsgi.py     : wsgiref模块
  --mange.py : django的入口文件
  --db.sqlite3 : django自带的sqlite3数据库(小型数据库,功能不是很多,还有bug)
  --app01文件夹
    ---admin.py    : django后台管理
    ---apps.py     : 注册使用
    ---migrations文件夹  : 所有的数据库迁移记录(类似于日志)
    ---models.py   : 数据库相关的 模型类(orm)
    ---test.py     : 测试文件
    ---views.py    : 视图函数(视图层)

Pycharm

方式一:

image

方式二:
image

image

image

命令行与pycharm创建区别

命令行创建不会自动生成templates文件夹,需要自己手动创建,而pycharm会自动创建,并且pycharm还会自动在配置文件中配置对应的路径。

pycharm 创建 settings.py 文件中

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')] # 拼接当前文件夹templates路径
        ,
        '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',
            ],
        },
    },
]

命令行创建

需要手动添加[os.path.join(BASE_DIR, 'templates')] 以及 手动创建templates文件夹

TEMPLATES = [
    {
      'BACKEND': 'django.template.backends.django.DjangoTemplates',
      'DIRS': [],
    }
]

注意:创建的应用一定要去配置文件中注册

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config', # 全写
    'app02'                  # 简写
]

创建出来的应用第一步先去配置文件中注册。

简单的看下配置文件有什么配置

# 当前项目路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 上线之后改为Flase
DEBUG = True
# 上线之后可写*表所有
ALLOWED_HOSTS = []
# 注册的app(功能模块)
INSTALLED_APPS
# django中间件
MIDDLEWARE
# HTML文件存放路径配置
TEMPLATES
# 项目指定的数据库
DATABASES

image

django必备三板斧

  • HttpResponse
  • render
  • redirect

HttpResponse:返回字符串类型

举例:

djangoday02/urls

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 自定义对应关系,路由与视图函数对应关系
    url(r'^index/', views.index)
]

app01/views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def index(request):
    """

    :param request: 请求相关所有数据对象,比之前的env功能更多。
    :return:
    """
    return HttpResponse("嘿嘿嘿")

image

结论:HttpResponse 返回字符串类型。

render:返回HTML文件

app01/views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def index(request):
    """

    :param request: 请求相关所有数据对象,比之前的env功能更多。
    :return:
    """
    
    """
    自动前往templates寻找HTML文件
    djangoday02/settings.py中TEMPLATES路径作用
    """
    return render(request,'myifrst.html')

image

结论:render 返回HTML文件

redirect:重定向

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
def index(request):
    """

    :param request: 请求相关所有数据对象,比之前的env功能更多。
    :return:
    """

    return redirect('https://www.baidu.com/')

跳转至百度。

posted @ 2022-02-25 12:35  谢俊杰  阅读(90)  评论(0编辑  收藏  举报