01 Django框架简介

Web框架本质

我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。

半成品自定义web框架

import socket

server = socket.socket()
server.bind(("127.0.0.1", 80))
server.listen()


while True:
   conn, addr = server.accept()
   data = conn.recv(8096)
   conn.send(b"OK")
   conn.close()

可以说Web服务本质上都是在这十几行代码基础上扩展出来的。这段代码就是它们的祖宗。

用户的浏览器一输入网址,会给服务端发送数据,那浏览器会发送什么数据?怎么发?这个谁来定? 你这个网站是这个规定,他那个网站按照他那个规定,这互联网还能玩么?

所以,必须有一个统一的规则,让大家发送消息、接收消息的时候有个格式依据,不能随便写。

这个规则就是HTTP协议,以后浏览器发送请求信息也好,服务器回复响应信息也罢,都要按照这个规则来。

HTTP协议主要规定了客户端和服务器之间的通信格式,那HTTP协议是怎么规定消息格式的呢?

让我们首先打印下我们在服务端接收到的消息是什么。

import socket

server = socket.socket()
server.bind(("127.0.0.1", 80))
sk.listen()


while True:
   conn, addr = server.accept()
   data = conn.recv(8096)
   print(data)  # 将浏览器发来的消息打印出来
   conn.send(b"OK")
   conn.close()

输出:

b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nDNT: 1\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=RKBXh1d3M97iz03Rpbojx1bR6mhHudhyX5PszUxxG3bOEwh1lxFpGOgWN93ZH3zv\r\n\r\n'

然后我们再看一下我们访问博客园官网时浏览器收到的响应信息是什么。

响应相关信息可以在浏览器调试窗口的network标签页中看到。

img

点击view source之后显示如下图:

img

我们发现收发的消息需要按照一定的格式来,这里就需要了解一下HTTP协议了。

HTTP协议介绍

HTTP协议对收发消息的格式要求

每个HTTP请求和响应都遵循相同的格式,一个HTTP包含Header和Body两部分,其中Body是可选的。 HTTP响应的Header中有一个 Content-Type表明响应的内容格式。如 text/html表示HTML网页。

HTTP GET请求的格式:

img

 

HTTP响应的格式:

img

 

处女版自定义web框架

经过上面的补充学习,我们知道了要想让我们自己写的web server端正经起来,必须要让我们的Web server在给客户端回复消息的时候按照HTTP协议的规则加上响应状态行,这样我们就实现了一个正经的Web框架了。

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8000))
sock.listen()

while True:
   conn, addr = sock.accept()
   data = conn.recv(8096)
   # 给回复的消息加上响应状态行
   conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
   conn.send(b"OK")
   conn.close()

我们通过十几行代码简单地演示了web 框架的本质。

接下来就让我们继续完善我们的自定义web框架吧!

根据不同的路径返回不同的内容

这样就结束了吗? 如何让我们的Web服务根据用户请求的URL不同而返回不同的内容呢?

小事一桩,我们可以从请求相关数据里面拿到请求URL的路径,然后拿路径做一个判断...

"""
根据URL中不同的路径返回不同的内容
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


while 1:
   # 等待连接
   conn, add = sk.accept()
   data = conn.recv(8096)  # 接收客户端发来的消息
   # 从data中取到路径
   data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
   # 第二种解码方式
   # data = data_decode('utf8')
   # 按\r\n分割
   data1 = data.split("\r\n")[0]
   url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
   conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
   # 根据不同的路径返回不同内容
   if url == "/index/":
       response = b"index"
   elif url == "/home/":
       response = b"home"
   else:
       response = b"404 not found!"

   conn.send(response)
   conn.close()

根据不同的路径返回不同的内容--函数版

上面的代码解决了不同URL路径返回不同内容的需求。

但是问题又来了,如果有很多很多路径要判断怎么办?难道要挨个写if判断? 当然不用,我们有更聪明的办法。

"""
根据URL中不同的路径返回不同的内容--函数版
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
   s = "这是{}页面!".format(url)
   return bytes(s, encoding="utf8")


def home(url):
   s = "这是{}页面!".format(url)
   return bytes(s, encoding="utf8")


while 1:
   # 等待连接
   conn, add = sk.accept()
   data = conn.recv(8096)  # 接收客户端发来的消息
   # 从data中取到路径
   data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
   # 第二种解码方式
   # data = data.decode('utf8')
   # 按\r\n分割
   data1 = data.split("\r\n")[0]
   url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
   conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
   # 根据不同的路径返回不同内容,response是具体的响应体
   if url == "/index/":
       response = index(url)
   elif url == "/home/":
       response = home(url)
   else:
       response = b"404 not found!"

   conn.send(response)
   conn.close()

根据不同的路径返回不同的内容--函数进阶版

看起来上面的代码还是要挨个写if判断,怎么办?我们还是有办法!(只要思想不滑坡,方法总比问题多!)

"""
根据URL中不同的路径返回不同的内容--函数进阶版
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
   s = "这是{}页面!".format(url)
   return bytes(s, encoding="utf8")


def home(url):
   s = "这是{}页面!".format(url)
   return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
  ("/index/", index),
  ("/home/", home),
]

while 1:
   # 等待连接
   conn, add = sk.accept()
   data = conn.recv(8096)  # 接收客户端发来的消息
   # 从data中取到路径
   data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
   # 第二种解码方式
   # data = data.decode('utf8')
   # 按\r\n分割
   data1 = data.split("\r\n")[0]
   url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
   conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
   # 根据不同的路径返回不同内容
   func = None  # 定义一个保存将要执行的函数名的变量
   for i in list1:
       if i[0] == url:
           func = i[1]
           break
   if func:
       response = func(url)
   else:
       response = b"404 not found!"

   # 返回具体的响应消息
   conn.send(response)
   conn.close()

返回具体的HTML文件

完美解决了不同URL返回不同内容的问题。 但是我不想仅仅返回几个字符串,我想给浏览器返回完整的HTML内容,这又该怎么办呢?

没问题,不管是什么内容,最后都是转换成字节数据发送出去的。 我们可以打开HTML文件,读取出它内部的二进制数据,然后再发送给浏览器。

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回独立的HTML页面
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
   # 读取index.html页面的内容
   with open("index.html", "r", encoding="utf8") as f:
       s = f.read()
   # 返回字节数据
   return bytes(s, encoding="utf8")


def home(url):
   with open("home.html", "r", encoding="utf8") as f:
       s = f.read()
   return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
  ("/index/", index),
  ("/home/", home),
]

while 1:
   # 等待连接
   conn, add = sk.accept()
   data = conn.recv(8096)  # 接收客户端发来的消息
   # 从data中取到路径
   data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
   # 第二种方法
   data = data.decode('utf8')
   # 按\r\n分割
   data1 = data.split("\r\n")[0]
   url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
   conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
   # 根据不同的路径返回不同内容
   func = None  # 定义一个保存将要执行的函数名的变量
   for i in list1:
       if i[0] == url:
           func = i[1] # 得到函数的内存地址
           break
   if func:
       response = func(url)
   else:
       response = b"404 not found!"

   # 返回具体的响应消息
   conn.send(response)
   conn.close()

让网页动态起来

这网页能够显示出来了,但是都是静态的啊。页面的内容都不会变化的,我想要的是动态网站。

没问题,我也有办法解决。我选择使用字符串替换来实现这个需求。(这里使用时间戳来模拟动态的数据)

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回HTML页面
让网页动态起来
"""

import socket
import time

sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(url):
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
        now = str(time.time())
        s = s.replace("@@oo@@", now)  # 在网页中定义好特殊符号,用动态的数据去替换提前定义好的特殊符号
    return bytes(s, encoding="utf8")


def home(url):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按\r\n分割
    data1 = data.split("\r\n")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    func = None  # 定义一个保存将要执行的函数名的变量
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"

    # 返回具体的响应消息
    conn.send(response)
    conn.close()

好了,在这停顿...

服务器程序和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

 

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

 

从这继续...

wsgiref

我们利用wsgiref模块来替换我们自己写的web框架的socket server部分:

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回HTML页面
让网页动态起来
wsgiref模块版
"""

import time
from wsgiref.simple_server import make_server


# 将返回不同的内容部分封装成函数
def index(url):
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
        now = str(time.time())
        s = s.replace("@@oo@@", now)
    return bytes(s, encoding="utf8")


def home(url):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]


def run_server(request, response):
     """
    :param request:跟请求相关的数据
    :param response: 跟响应相关的数据
    :return: 返回值就是要给前端浏览器的数据
    """
    response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息,自动帮我们处理了所有http协议相关的数据并组织成了一个大字典
    url = request.get('PATH_INFO')  # 取到用户输入的url
    func = None
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"
    return [response, ]


if __name__ == '__main__':
     # 监听127.0.0.1:8080 一旦有请求 立刻将第三个参数加括号调用
    server = make_server('127.0.0.1', 8080, run_server)
    print("我在8080等你哦...")
    server.serve_forever()

jinja2

上面的代码实现了一个简单的动态,我完全可以从数据库中查询数据,然后去替换html中的对应内容,然后再发送给浏览器完成渲染。 这个过程就相当于HTML模板渲染数据。 本质上就是HTML内容中利用一些特殊的符号来替换要展示的数据。 我这里用的特殊符号是我定义的,其实模板渲染有个现成的工具: jinja2

该模块提供了"模板语法"
	支持后端给html页面传递数据并且支持后端语法
pip3 install jinja2

<h1>{{user_dict}}</h1>
<h1>{{user_dict['username']}}</h1>
<h1>{{user_dict.get('pwd')}}</h1>
<h1>{{user_dict.hobby}}</h1>

<div>
    {% for key in user_dict%}
        <p>{{ key }}</p>
    {% endfor %}
</div>

下载jinja2:

pip install jinja2
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
</head>
<body>
    <h1>姓名:{{name}}</h1>
    <h1>爱好:</h1>
    <ul>
        {% for hobby in hobby_list %}
        <li>{{hobby}}</li>
        {% endfor %}
    </ul>
</body>
</html>

使用jinja2渲染index2.html文件:

from wsgiref.simple_server import make_server
from jinja2 import Template


def index():
    with open("index2.html", "r") as f:
        data = f.read()
    template = Template(data)  # 生成模板文件
    ret = template.render({"name": "Alex", "hobby_list": ["烫头", "泡吧"]})  # 把数据填充到模板里面
    return [bytes(ret, encoding="utf8"), ]


def home():
    with open("home.html", "rb") as f:
        data = f.read()
    return [data, ]


# 定义一个url和函数的对应关系
URL_LIST = [
    ("/index/", index),
    ("/home/", home),
]


def run_server(request, response):
    response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = request['PATH_INFO']  # 取到用户输入的url
    func = None  # 将要执行的函数
    for i in URL_LIST:
        if i[0] == url:
            func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
            break
    if func:  # 如果能找到要执行的函数
        return func()  # 返回函数的执行结果
    else:
        return [bytes("404没有该页面", encoding="utf8"), ]


if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()

现在的数据是我们自己手写的,那可不可以从数据库中查询数据,来填充页面呢?

使用pymysql连接数据库:

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306, 
    user="root", 
    passwd="xxx", 
    db="xxx", 
    charset="utf8"
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select name, age, department_id from userinfo")
user_list = cursor.fetchall()
cursor.close()
conn.close()

创建一个测试的user表:

CREATE TABLE user(
  id int auto_increment PRIMARY KEY,
  name CHAR(10) NOT NULL,
  hobby CHAR(20) NOT NULL
)engine=innodb DEFAULT charset=UTF8;

模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。

Django

Django官网下载页面

python主流web框架

'''千万不要同时学习多个框架!!!'''
django框架
	大而全 内部自带的组件特别特别多 类似于航空母舰
    有时候可能会过于"笨重"
    
flask框架
	小而精 内部几乎没有什么自带的组件 全部依赖于第三方模块 类似于游骑兵
    如果将flask所有的第三方模块集合到一起甚至可以盖过django
    有时候可能会出现第三方模块无法兼容的情况

tornado框架
	异步非阻塞
    """
    同步异步
    	同步:提交任务之后原地等待任务的返回结果 期间不做任何事
    	异步:提交任务之后不原地等待任务返回结果 有结果会通过回调机制反馈
    阻塞非阻塞
    	阻塞:程序被剥夺了CPU执行权限
    	非阻塞:运行态 就绪态
    """
A:socket部分
B:路由匹配
C:模板语法
    
django
	A:不是自己写的 用的wsgiref模块
    B:自己写的
    C:自己写的
flask
	A:不是自己写的 werkzeug(依赖于wsgiref模块)
    B:自己写的
    C:不是自己写的 jinja2
Tornado
	A,B,C全部都是自己写的

    
知识储备:    
    fastapi框架
        异步框架

安装(安装最新LTS版):

pip3 install django==1.11.9

验证django是否下载完毕
	django-admin

创建一个django项目:

下面的命令创建了一个名为"mysite"的Django 项目:

django-admin startproject mysite

目录介绍:

mysite/
├── manage.py  # 管理文件
└── mysite  # 项目目录
    ├── __init__.py
    ├── settings.py  # 配置
    ├── urls.py  # 路由 --> URL和函数的对应关系
    └── wsgi.py  # runserver命令就使用wsgiref模块做简单的web server
mysite文件夹
	mysite同名文件夹
    	settings.py
        	# django暴露给用户可以自定义配置的文件
         urls.py
        	# 存放路由(路径)与函数(视图函数)对应关系
         wsgi.py
        	# 依赖于wsgiref模块的socket启动部分
    manage.py文件
    	# django的入口(启动)文件
    app01文件夹
    	migrations文件夹
        	# 里面存放ORM针对数据库相关的记录
        admin.py
        	# django自带的后台管理功能
        apps.py
        	# 每个应用的独立标识
        models.py
        	# 与数据库打交道的文件(ORM)
        tests.py
        	# 自带的测试文件
        views.py
        	# 该app对应的主体功能(函数 类)
    db.sqlite3
    	# django自带的小型数据库(针对日期格式无法精准存取)
  
django是可以自动重启的 但是有时候自动重启的反应时间有点长

 

运行Django项目:

python manage.py runserver 127.0.0.1:8000

模板文件配置:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "template")],  # template文件夹位置
        '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',
            ],
        },
    },
]

django基本使用

命令行
	1.创建django项目
    	django-admin startproject 项目名
    2.如何运行django项目
    	切到项目目录下
        	cd 项目名
        python3 manage.py runserver
			# 可能会报错 需要删除widgets.py 152行逗号
    3.创建app
    	python3 manage.py startapp app名字
    
"""
命令行创建不会自动创建templates文件夹 并且配置文件中也不会配置
需要自己创建文件夹并配置
	os.path.join(BASE_DIR, 'templates')
"""

静态文件配置:

STATIC_URL = '/static/'  # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),  # 静态文件存放位置
]

看不明白?有图有真相:

img

刚开始学习时可在配置文件中暂时禁用csrf中间件,方便表单提交测试。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

html接口前缀动态配置

	{% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>

网络请求方式

1.get请求
	朝别人索要数据
    eg:浏览器地址栏输入www.baidu.com回车
        get请求没有请求体
        get请求也可以携带一些的额外的参数 但是大小有限制(2KB)
        	url?xxx=yyy&aaa=bbb
            
2.post请求
	朝别人提交数据
    eg:用户注册登录填写完身份数据之后提交
        post请求有请求体
        post请求也可以携带数据 并且大小没有限制 在请求体中

form表单重要参数

action  # 控制数据提交的地址
	1.写全路径  https://www.baidu.com
	2.写后缀(ip和端口自动补全当前服务器)    /index/
    3.不写  提交给当前页面所在的地址
method  # 控制数据提交的方式
	get  form表单默认是get请求
    post
  
"""
注意使用django前期在提交post请求之前需要去配置文件中注释掉一行代码
	MIDDLEWARE = [
    	# 'django.middleware.csrf.CsrfViewMiddleware',
	]
"""

request对象方法

request.method  # 获取请求方式名(纯大写的字符串)
request.POST  # 获取post请求提交的普通数据  <QueryDict: {'username': ['jason'], 'password': ['123']}>
	request.POST.get()
    request.POST.getlist()
request.GET  # 获取get请求url问号后面的数据	
	request.GET.get()
    request.GET.getlist()
    
def login(request):  
    if request.method == 'POST':
        username = request.POST.get('username')  # 默认只会取列表最后一个元素
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            return HttpResponse('OK')
        else:
            return HttpResponse('用户名或密码错误')
    return render(request, 'login.html')

django链接MySQL(必会)

# 第一步配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '数据库名称',
        'USER':'root',
        'PORT':3306,
        'HOST':'127.0.0.1',
        'PASSWORD':'123',
        'CHARSET':'utf8'
    }
}
# 第二步配置(3.6及以下解释器 需要额外的配置)
import pymysql
pymysql.install_as_MySQLdb()
'''只要是__init__文件即可 项目的 应用的都可以'''

 

Django基础必备三件套:

from django.shortcuts import HttpResponse, render, redirect

HttpResponse

内部传入一个字符串参数,返回给浏览器。

def index(request):
    # 业务逻辑代码
    return HttpResponse("OK")

render

除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数

将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2)

def index(request):
    # 业务逻辑代码
    return render(request, "index.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})

'''
render(request,'index.html',{'n1':[1,2,3]})  # 精准传(复杂但节省资源)
render(request,'index.html',locals())  # 范围传(简单但不节省资源)
返回给前端浏览器html页面 并且提供模板语法
'''

redirect

接受一个URL参数,表示跳转到指定的URL。

def index(request):
    # 业务逻辑代码
    return redirect("/home/")

重定向是怎么回事?

img

 

 

课后练习:

Django版登录

启动Django报错:

Django 启动时报错 “UnicodeEncodeError ...”

报这个错误通常是因为计算机名为中文,改成英文的计算机名重启下电脑就可以了。

Django 启动报错“SyntaxError: Generator expression must be parenthesized”

报这个错很大可能是因为使用了Python3.7.0,而目前(2018-06-12)Python3.7.0和Django还有点兼容性问题,换回Python3.6的环境即可。

posted @ 2022-04-15 16:22  vonmo  阅读(24)  评论(0编辑  收藏  举报