动静态网页
静态网页: 数据是写死的, 不会变化, 除非直接修改 html 文件
动态网页: 数据是动态获取的, 例如获取当前时间, 或者从数据库中获取数据, 当数据库中的数据被修改后, 会将被修改的数据动态展示到网页中.
jinja2 模块
提供了一个可以在 HTML 页面上书写类似于 python 后端的代码 来操作数据 (模板语法)
安装: pip3 install jinja2
flask 框架模板语法使用的就是 jinja2 模块, 所以你只要下了 flask 框架 就会自动下载 jinja2
模板语法是在后端实现的, 前端不识别.
模板语法:
<-- 模板语法 (jinja2 模板语法非常贴近 python 语法 但是并不是所有的框架使用的都是 jinja 模板语法) /-->
写在 HTML 文件中
- {
- {
- xxx
- }
- }
- <p>{
- {
- xxx.username
- }
- }</p>
- <p>{
- {
- xxx['password']
- }
- }</p>
- <p>{
- {
- xxx.get('hobby')
- }
- }</p>
- <p>{
- {
- xxx.get('hobby')[0]
- }
- }</p>
- <p>{
- {
- xxx.get('hobby').1
- }
- }</p>
for 循环:
- {%for user_dict in xxx %}
- <tr>
- <td>{{ user_dict.id }}</td>
- <td>{{ user_dict.name }}</td>
- <td>{{ user_dict.hobby }}</td>
- </tr>
- {% endfor %}
手写 web 简易框架
处理请求的代码:
- import socket
- server = socket.socket()
- server.bind(('localhost', 8080))
- server.listen(5)
- """
- 请求首行
- b'GET / HTTP/1.1\r\n
- 请求头
- Host: 127.0.0.1:8080\r\n
- Connection: keep-alive\r\n
- Cache-Control: max-age=0\r\n
- Upgrade-Insecure-Requests: 1\r\n
- User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36\r\n
- Sec-Fetch-User: ?1\r\n
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
- Sec-Fetch-Site: cross-site\r\n
- Sec-Fetch-Mode: navigate\r\n
- Accept-Encoding: gzip, deflate, br\r\n
- Accept-Language: zh-CN,zh;q=0.9\r\n
- 空行, 代表不再有请求头
- \r\n
- 下面是请求体, 因为是 get 请求, 因此请求体无数据
- """
- while True:
- conn, addr = server.accept()
- # 将请求体转为字符串格式
- data = conn.recv(1024).decode('utf-8')
- conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
- # 对转换后的数据进行切分 (依据空格切分), 获取到请求的路径
- target_url = data.split(' ')[1]
- if target_url == '/index':
- conn.send(b'index')
- elif target_url == '/login':
- # 如果路径为 / login 就返回 HTML 文件
- with open('login.html', 'rb') as f:
- conn.send(f.read())
- else:
- # 如果请求页面不存在, 返回 404 响应状态码
- conn.send(b'404 NOT FIND')
- conn.close()
引用的 login.HTML 文件内容如下:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- login
- </title>
- </head>
- <body>
- <p>
- is login...
- </p>
- </body>
- </HTML>
基于 wsgire 模块手写简易版 Web 框架
我们可以发现上面的代码, 如果 browser 客户端请求的路径有上百个, 我们就需要写上对应数量的 if 语句, 以及对应的返回数据, 这样程序的可扩展性差, 且所有的判断和返回的数据都在一个文件中, 显得杂乱.
根据功能不同拆分成不同的文件, 用户可以在 browser 窗口中输入 url 之后可以获取到对应的资源.
文件拆分:
urls.py: 路由与视图函数的对应关系
views.py: 里面放视图函数 (视图函数可以是函数也可以是类)
templates 文件夹: 模板文件夹 (里面存放的就是一堆 HTML 文件)
views.py 中代码:
- def index(env):
- return 'index'
- def login(env):
- return 'login'
- def error(env):
- return '404 NOT FIND'
- import time
- # 该函数需要返回一个 HTML 页面
- def get_time(env):
- current_time = time.strftime('%Y-%m-%d %X')
- with open(r'G:\python 项目 \ day49\templates\02 get_time.html', 'r', encoding='utf-8') as f:
- data = f.read()
- data = data.replace('gfdgsfdgfdsgsfdgsfdgsfdgsdg', current_time) # 利用字符串的替换
- return data
- from jinja2 import Template
- def get_user(env):
- user_dict = {'username': 'jason', 'password': 123, 'hobby': ['read', 'study', 'run']}
- with open(r'G:\python 项目 \ day49\templates\03 get_user.html', 'r', encoding='utf-8') as f:
- data = f.read()
- temp = Template(data)
- res = temp.render(xxx=user_dict)
- return res
- import pymysql
- def get_info(env):
- conn = pymysql.connect(
- host='127.0.0.1',
- port='3306',
- user='root',
- password='123',
- database='day49',
- charset='utf-8',
- autocommit=True
- )
- cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
- sql = "select * from userinfo"
- cursor.execute(sql)
- data = cursor.fetchall() # 返回的数据是列表套字典
- # 将列表套字典的结构数据 直接传递给 HTML 页面
- with open(r'G:\python 项目 \ day49\templates\04 get_info.html', 'rb', encoding='utf-8') as f:
- data = f.read()
- # 利用 jinja2 模块
- tmp = Template(data)
- # 利用对象的 render 方法 将数据直接传递给 HTML 页面
- res = tmp.render(xxx=data)
- return res
urls.py 中代码:
- from views import *
- urls = [
- ('/index',index),
- ('/login', login),
- ('/get_time', get_time),
- ('/get_user', get_user),
- ('/get_info', get_info)
- ]
templates 文件夹:
python 三大主流 Web 框架
Django
优点: 大而全, 自身携带的组件特别多
缺点: 笨重
flask(源码 600 多行, 分为两部分: 请求上下文, 应用上下文)
优点: 小而精, 自身携带的组件和功能少, 但第三方支持该框架的模块特别多, 如果全部叠加起来可以超越 django
缺点: 第三方模块不是 flask 写的, 随着 flask 的版本更新, 第三方模块需要去兼容 flask, 会引发兼容性问题, 因此受限于第三方模块
tornado
异步非阻塞
天然支持高并发
Django 框架部署准备
Windows 安装注意事项:
计算机名称不能有中文
python 解释器的版本不能超过 3.7(3.7 的版本有 bug)
推荐使用 1.x 版本 (1.11.09~1.11.13)
如果你已经按照过不需要手动卸载 重新安会自动先卸载之前的版本再安装
安装命令:
- # 在 cmd 窗口中执行
- pip3 install django==1.11.11
- # 临时使用其他源安装
- pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn django==1.11.11
测试是否安装成功:
- # 命令行中输入
- django-admin
如何创建 django 项目
命令行
- # 先切换到要创建 django 项目的目录下
- cd project
- # 执行创建项目的命令
- django-admin startproject mysite # mysite: 项目名
- # 此时会在项目文件下出现以下文件和目录
- D:.
│ manage.py
│
└─mysite
settings.py
urls.py
wsgi.py
__init__.py
- # 启动 django 项目 (先切换到项目目录下)
- python manage.py runserver # django 的默认端口号 8000
- # 此时可以在浏览器中输入 ip 加端口号访问 django
- # 例如: http://127.0.0.1:8000/
- # 打开的网页提示你创建独立功能的 App
- # python manage.py startapp [app_label]
- python manage.py startapp app01
- # 此时会多出来一个 app1 目录
目录: D:\mydjango\mysite
- Mode LastWriteTime Length Name
- ---- ------------- ------ ----
- d----- 2020/1/3 19:54 app01
- d----- 2020/1/3 19:50 mysite
- -a---- 2020/1/3 19:50 12288 db.sqlite3
- -a---- 2020/1/3 19:36 826 manage.py
- # cd 到 app1 中, 查看目录
- cd app01
- # app1 中的目录
卷序列号为 0FD0-081A
D:.
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└─migrations
__init__.py
注意点:
1, 使用命令行创建的 django 项目是不会自动创建 templates 摸版本文件夹 你只能自己手动创建
2, 命令行创建的 django 项目不但没有 templates 文件夹配置文件中也没有填写路径, 而 pycharm 创建的会自动添加
如果不做这步操作, 后面导入 HTML 文件时, 路径需要写全路径, 无法直接引用 HTML 文件
因此我们要去手动创建 templates 文件夹:
- # 在项目目录下执行, 就是和 manage.py 文件同级的目录
- mkdir templates
手动将创建的目录添加到配置文件中:
- # settings.py 在项目配置文件中第 54 行修改
- # 修改 TEMPLATES 中的'DIRS': [os.path.join(BASE_DIR, 'templates')]
需要将创建的 App 在 settings 中 INSTALLED_APPS 注册上
- # 我们创建的 App 也必须先在这个地方注册之后才能正常执行
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- # 注册我们自己的 App
- # 'app01' # 简写
- 'app01.apps.App01Config' # 完整写法
- ]
此时可以在 urls.py 中添加路由和视图的关系
- # 这里的 urls.py 可以使用 settings.py 目录下的同级 urls.py, 也可以在我们创建的应用 app01 下新建 urls.py
- # 这里我们使用 settings.py 同级目录下的 urls.py
- from django.conf.urls import url
- from django.contrib import admin
- # 导入我们创建的 app01 中的视图函数文件
- from app01 import views
- urlpatterns = [
- url(r'^admin/', admin.site.urls),
- # 新增以下的路由和视图的关系
- url(r'^index/', views.index),
- url(r'^login/', views.login),
- url(r'^home/', views.home),
- ]
再去 app01 目录下 views.py 文件中, 创建我们的视图函数
- # 将 render,HttpResponse,redirect 导入
- from django.shortcuts import render, HttpResponse, redirect
- # Create your views here.
- # 定义的视图函数都必须传入 request
- def index(request):
- return HttpResponse('你好啊小妹妹')
- def login(request):
- return render(request, 'login.html', {'user_dic': {'username': 'json', 'password': 123}, 'mes': 'hello'})
- def home(request):
- return redirect('https://www.baidu.com')
login.HTML 文件
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- </head>
- <body>
- {# 取字典中的值 #} {{ user_dic.username }}
- </body>
- </HTML>
pycharm 快速创建
点击导航条上方的 File ---> New Project ---> Django(此处注意不要使用虚拟环境, 也不要取消勾选 Enable Django admin) ---> Create ---> New Windows ---> 完成
django 的 settings.py 文件
- """
- Django settings for mysite project.
- Generated by 'django-admin startproject' using Django 1.11.11.
- For more information on this file, see
- https://docs.djangoproject.com/en/1.11/topics/settings/
- For the full list of settings and their values, see
- https://docs.djangoproject.com/en/1.11/ref/settings/
- """
- import os
- # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
- BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- # Quick-start development settings - unsuitable for production
- # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
- # SECURITY WARNING: keep the secret key used in production secret!
- SECRET_KEY = 'lb2x()gw&p)10ob6=zky-9_62)fmy#-+m06)kzp8gi+6d*hv18'
- # SECURITY WARNING: don't run with debug turned on in production!
- DEBUG = True
- ALLOWED_HOSTS = []
- # Application definition
- # 已经安装过的 App
- # 我们创建的 App 也必须先在这个地方注册之后才能正常执行
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- # 注册我们自己的 App
- # 'app01' # 简写
- 'app01.apps.App01Config' # 完整写法
- ]
- # 中间件
- 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',
- ]
- ROOT_URLCONF = 'mysite.urls'
- # 模板文件夹配置
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, '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',
- ],
- },
- },
- ]
- WSGI_APPLICATION = 'mysite.wsgi.application'
- # Database
- # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
- }
- }
- # Password validation
- # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
- AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
- ]
- # Internationalization
- # https://docs.djangoproject.com/en/1.11/topics/i18n/
- LANGUAGE_CODE = 'en-us'
- TIME_ZONE = 'UTC'
- USE_I18N = True
- USE_L10N = True
- USE_TZ = True
- # Static files (CSS, JavaScript, Images)
- # https://docs.djangoproject.com/en/1.11/howto/static-files/
- STATIC_URL = '/static/'
django 使用时注意点
代码修改了始终没有效果
在同一个端口下起来多个服务, 一直跑的是最开始的那个服务
浏览器缓存问题
django 能够自动重启, 但是他的重启机制只要检测到你的代码有变化, 在一定时间间隔内就会自动重启, 所以有时候可能会出现你的代码还没写完, 就已经自动重启了.
django 小白必回三板斧
HttpResponse
返回的是字符串
- def index(request):
- return HttpResponse('你好啊小妹妹')
- render
返回 HTML 页面 并且可以给 HTML 页面传数据
- def login(request):
- return render(request, 'login.html', {'user_dic': {'username': 'json', 'password': 123}, 'mes': 'hello'})
- # 返回 HTML 页面, 并可以给 HTML 传入字典
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- </head>
- <body>
- {# 取字典中的值 #} {{ user_dic.username }}
- </body>
- </HTML>
redirect
重定向
- def home(request):
- return redirect('https://www.baidu.com')
来源: http://www.bubuko.com/infodetail-3364425.html