初识Django
前言:
本章主要是对web框架做一个基础了解,为了接下来学习前端框架做铺垫
必备知识点:
- 什么是路由
路由简单的来说就是根据用户请求的 URL 链接来判断对应的处理程序,并返回处理结果,也就是 URL 与 Django 的视图建立映射关系。
Django 路由在 urls.py 配置,urls.py 中的每一条配置对应相应的处理方法。路由简单的来说就是根据用户请求的 URL 链接来判断对应的处理程序,并返回处理结果,也就是 URL 与 Django 的视图建立映射关系。
Django 路由在 urls.py 配置,urls.py 中的每一条配置对应相应的处理方法。
- 前端请求方式
GET,表示向服务器获取资源
POST,表示向服务器提交信息,通常用于产生新的数据,比如注册
PUT,表示希望修改服务器的数据,通常用于修改
DELETE,表示希望删除服务器的数据
OPTIONS,发生在跨域的预检请求中,表示客户端向服务器申请跨域提交
TRACE,回显服务器收到的请求,主要用于测试和诊断
CONNECT,用于建立连接管道,通常在代理场景中使用,网页中很少用到GET,表示向服务器获取资源
POST,表示向服务器提交信息,通常用于产生新的数据,比如注册
PUT,表示希望修改服务器的数据,通常用于修改
DELETE,表示希望删除服务器的数据
OPTIONS,发生在跨域的预检请求中,表示客户端向服务器申请跨域提交
TRACE,回显服务器收到的请求,主要用于测试和诊断
CONNECT,用于建立连接管道,通常在代理场景中使用,网页中很少用到
GET和POST的区别
从 http 协议的角度来说,GET 和 POST 它们都只是请求行中的第一个单词,除了语义不同,其实没有本质的区别。
之所以在实际开发中会产生各种区别,主要是因为浏览器的默认行为造成的。
受浏览器的影响,在实际开发中,GET 和 POST 有以下区别:
- 浏览器在发送 GET 请求时,不会附带请求体
- GET 请求的传递信息量有限,适合传递少量数据;POST 请求的传递信息量是没有限制的,适合传输大量数据。
- GET 请求只能传递 ASCII 数据,遇到非 ASCII 数据需要进行编码;POST 请求没有限制
- 大部分 GET 请求传递的数据都附带在 path 参数中,能够通过分享地址完整的重现页面,但同时也暴露了数据,若有敏感数据传递,不应该使用 GET 请求,至少不应该放到 path 中
- 刷新页面时,若当前的页面是通过 POST 请求得到的,则浏览器会提示用户是否重新提交。若是 GET 请求得到的页面则没有提示。
- GET 请求的地址可以被保存为浏览器书签,POST 不可以
- 纯手撸web框架
在写代码之前需要先了解web框架的本质是什么?
- 本质上web框架就是将前端与后端串联起来的一个中间介质,这是代码实现web的本质
- 框架的本质就好像是房子的主体结构一样,规定了这个放在必须按照这个规格建造,而框架也是如此
在写web框架之前需要先理一下如何写web框架的思路,思路如下
- 编写Socket服务端代码
服务端代码在返回信息时需要使用http协议返回 - 根据URL路由获取不同的页面内容
获取用户输入的后缀>>>: 请求数据信息GET信息
3.处理请求数据获取路由
# 文件 socket_server.py
import socket
server = socket.socket() # TCP
server.bind(('127.0.0.1', 8888)) # IP PORT
server.listen(5) # 半连接池
while True:
sock, address = server.accept() # 等待链接
data = sock.recv(1024) # 字节(bytes)
sock.send(b'HTTP/1.1 200 OK\r\n\r\n')
data_str = data.decode('utf8') # 先转换成字符串
target_url = data_str.split(' ')[1] # 按照空格切割得到路由
if target_url == '/index':
with open(r'index.html', 'rb') as f:
sock.send(f.read())
elif target_url == '/login':
sock.send(b'login page')
else:
sock.send(b'home page!')
- 基于wsgire模块
wsgiref模块其实就是将整个请求信息给封装了起来,就不需要你自己处理了,假如它将所有请求信息封装成了一个叫做request的对象,
那么你直接request.path就能获取到用户这次请求的路径,request.method就能获取到本次用户请求的请求方式(get还是post)等,
"""
wsgire 是内置模块,现在很多主流的web框架都使用了这个模块
功能:
1 . 封装了socket代码
2. 处理请求数据
使用这个模块主要用来解决上面使用socket模块带来的一些问题
1. 固定代码启动服务端
2. 查看处理之后的request字典分析数据
3. 根据不同的路由返回不同的内容:根据request返回的数据处理
4. 针对于上述的 1 3 问题使用下列代码处理
"""
def run(request, response):
"""
:param request: 请求相关数据,是有模块处理好的大字典信息
:param response: 响应相关的数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式
path_info = request.get('PATH_INFO') # 请求头的信息
if path_info == '/index':
return [b'index']
elif path_info == '/login':
return [b'login']
return [b'hello wsgiref module']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # 实时监听服务端运行的端口,一旦有请求过来自动给第三个参数加括号传参并调用
server.serve_forever() # 启动服务端def run(request, response):
通过上述代码我们解决了 1 和 3 的问题也就是固定启动服务端,也可以得到request处理之后的大字典,关于最后我们需要对代码做优化和封装继续向下看
- 代码封装优化
为什么需要优化
- 路由匹配问题:如果路由很多如何匹配?代码重复率过高
- 匹配成功后执行的代码或页面有多有少,如何处理?
上面说了为什么要优化代码,以及上面代码带来的问题,接下来考虑如何优化
- 使用函数封装和模块拆分的方式拆分代码
- 将分支代码封装为一个一个的函数
- 将路由和函数名做对应关系
- 获取路由循环匹配
根据上述优化完成之后,向增加新的功能只需要添加对应函数和对应关系即可
文件的拆分:
views.py # 对应核心业务逻辑(功能函数)
urls.py # 存储路由和功能函数的存储关系
templates目录 # 为了防止html文件太多太乱,创建相应的文件夹存放
代码优化的准备工作已经可以了 ,接下来在优化代码之前,需要先了解一下什么是动静态网页和jinja2模版的语法和使用
- 动静态网页
简单来说静态页面就是与后端无交互,动态就是有交互,在优化时就需要将静态返回做为动态返回
- 静态网页:
静态网页
一般是编写好不会改变的,或者改变会从新编写的,数据来源是编写时就已经确定了,比如说宣传中的海报,请求方式为GET获取 - 动态网页:
在编写时数据来源并不固定,一般指的的来源于数据库,比如说网页上的登录时间展示等,需要向后端提交一定的信息,请求方式一般为POST
- jinja2模版语法与使用
这里是 Jinja2 通用模板语言的文档。 Jinja2 在其是一个 Python 2.4 库之前,被设计 为是灵活、快速和安全的这里是 Jinja2 通用模板语言的文档。 Jinja2 在其是一个 Python 2.4 库之前,被设计 为是灵活、快速和安全的
jinja2 在使用时可以处理接收的字典信息,并且可以使用句垫符,中括号,以及get的方式取值
代码优化
# 使用文件分离和jinja2对代码进行优化
1. 服务端代码 socket_server.py
from wsgiref.simple_server import make_server
from views import *
from urls import urls
def run(request, response):
"""
:param request: 请求相关数据,是有模块处理好的大字典信息
:param response: 响应相关的数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式
path_info = request.get('PATH_INFO') # 请求头的信息
func_name = None # 定义一个用于后续存储用户函数名的变量
for url_tuple in urls: # 函数名
if path_info == url_tuple[0]:
func_name = url_tuple[1]
break # 匹配成功后无需再向后匹配
if func_name:
res = func_name(request)
else:
res = error_func(request)
return [res.encode('utf8')]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # 实时监听服务端运行的端口,一旦有请求过来自动给第三个参数加括号传参并调用
server.serve_forever() # 启动服务端
2. views.py
from jinja2 import Template
def get_dict(request):
user_dict = {'name': 'jason', 'age': 18, 'person_list': ['阿珍', '阿强', '阿香', '阿红']}
with open(r'templates/get_dict_page.html', 'r', encoding='utf8') as f:
date = f.read()
temp_obj = Template(date) # 将页面数据使用模版处理
res = temp_obj.render({'user_dict': user_dict}) # 给页面传了一个 变量名是user_dict值是字典数据的数据
return res
def error_func(request):
return 'not a page'
def index(request):
return 'hello index'
def login(request):
return 'hello login'from jinja2 import Template
3. urls.py
from views import *
urls = [
('/index', index),
('/login', login),
('/get_dict', get_dict)
]
4. get_dict_page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>{{ user_dict }}</p>
<p>{{ user_dict.name }}</p>
<p>{{ user_dict['age'] }}</p>
<p>{{ user_dict.get('person_list') }}</p>
</body>
- 前端后端数据库联动
将数据库中的表以表格的形式在web前端展示
数据表及数据
mysql> desc userinfo;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.02 sec)
mysql> select * from userinfo;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 1 | xiaocheng | 38 |
| 2 | wesley | 18 |
| 3 | xiaowang | 28 |
| 4 | wesleyaaa | 18 |
| 5 | wang | 28 |
| 6 | wesley55 | 18 |
+----+-----------+-----+
6 rows in set (0.01 sec)
------------------------------联动代码----------------------
目录文件:
├── index.html
├── socket_server.py
├── templates
│ └── get_dict_page.html
├── urls.py
└── views.py
-----------socket_server.py-----------------------------
from wsgiref.simple_server import make_server
from views import *
from urls import urls
def run(request, response):
"""
:param request: 请求相关数据,是有模块处理好的大字典信息
:param response: 响应相关的数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式
path_info = request.get('PATH_INFO') # 请求头的信息
func_name = None # 定义一个用于后续存储用户函数名的变量
for url_tuple in urls: # 函数名
if path_info == url_tuple[0]:
func_name = url_tuple[1]
break # 匹配成功后无需再向后匹配
if func_name:
res = func_name(request)
else:
res = error_func(request)
return [res.encode('utf8')]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # 实时监听服务端运行的端口,一旦有请求过来自动给第三个参数加括号传参并调用
server.serve_forever() # 启动服务端
----------------------templates/get_dict_page.html----------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container"></div>
<div class="row">
<h1 class="text-center">数据展示</h1>
<a href="/index">点击跳转index</a>
<div class="col-md-8 col-md-offset-2">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
<!-- [{}{}{}]-->
{% for user_dict in user_data_list %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.age }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</body>
</html>
-----------------views.py--------------------
import pymysql
def get_user(request):
conn = pymysql.connect(
user='root',
password='Videojet2029@',
host='121.4.86.62',
port=3306,
db='django',
charset='utf8',
autocommit=True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from userinfo;"
cursor.execute(sql)
user_data = cursor.fetchall()
print(user_data)
# 读取数据
with open(r'templates/get_dict_page.html', 'r', encoding='utf8') as f:
data = f.read()
temp_obj = Template(data)
res = temp_obj.render({'user_data_list': user_data})
return resimport pymysql
----------------urls---------------
from views import *
urls = [
('/index', index),
('/login', login),
('/get_dict', get_dict),
('/get_user', get_user)
]
-
web主流框架介绍
1.django
大而全 自身自带的功能组件非常的多 类似于航空母舰
2.flask
小而精 自身自带的功能组件非常的少 类似于游骑兵
几乎所有的功能都需要依赖于第三方模块
3.tornado
异步非阻塞 速度极快效率极高甚至可以充当游戏服务端
ps:sanic、fastapi... -
django框架简介
注意事项
1.django项目中所有的文件名目录名不要出现中文
2.计算机名称尽量也不要出现中文
3.一个pycharm尽量就是一个完整的项目(不要嵌套 不要叠加)
4.不同版本的python解释器与不同版本的django可能会出现小问题
Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。
Django 是一个开放源代码的 Web 应用框架,由 Python 写成。
Django 遵守 BSD 版权,初次发布于 2005 年 7 月, 并于 2008 年 9 月发布了第一个正式版本 1.0 。
Django 采用了 MVT 的软件设计模式,即模型(Model),视图(View)和模板(Template)
- 名词解释
- 路由 用于判断用户需要请求页面的url后缀
- 函数 视图函数
- 视图类
- djando中的重要层级
- urls.py 路由层
- views.py 视图层
- models.py 模型层
- templates 模版层
- django基本操作命令
- 下载
pip3 install django # 如果输入太慢可以使用 -i 参数临时使用国内源
- 验证是否安装成功
wesley@***** ⮀ ~ ⮀ django-admin
····
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
····
- 常用指令
"""
1. 创建django项目
django-admin startproject [projectname]
2. 启动项目
cd projectname && python3 manage.py runserver ip:port
3. 创建app
python3 manage.py startapp [appname]
注意:使用命令新创建的app应用需要注册
创建的app一定要去settings.py中注册
INSTALLED_APPS = [
'app01.apps.App01Config', # 写法一
'app02' # 写法二
]
使用Pycharm创建项目的注意事项
1. 会自动创建templates文件夹,配置文件中可能会报错
更改/符号为:os.path.join(BASE_DRT, 'templates')
"""
-
django app 概念
django整体就类似是一所大学,app类似于大学中的各个学院,每个都是独立的
django里面的app类似于某个具体的功能模块
user app 所有的用户相关的都写在user app下
goods app 所有的商品相关的都卸载goods app下 -
django主要目录结构
wesley@wesley ⮀ ~/PycharmProjects/django_test ⮀ tree -L 3
.
├── django_test # django 项目名
│ ├── __init__.py # 包文件
│ ├── settings.py # 配置文件
│ ├── urls.py # 路由文件
│ └── wsgi.py # wsgiref网关文件
├── manage.py # 入口文件
└── templates # 存储html文件
django 项目目录名
django 项目同名目录
settings.py 配置文件
urls.py 存储网址后缀与函数名对应关系(不严谨)
wsgi.py wsgiref网关文件
db.sqlite3文件 django自带的小型数据库(项目启动之后才会出现)
manage.py 入口文件(命令提供)
应用目录
migrations目录 存储数据库相关记录
admin.py django内置的admin后台管理功能
apps.py 注册app相关
models.py 与数据库打交道的(非常重要)
tests.py 测试文件
views.py 存储功能函数(不严谨)
templates目录 存储html文件(命令行不会自动创建 pycharm会)
配置文件中还需要配置路径
[os.path.join(BASE_DIR,'templates'),]
- diango小白必会三板斧
# 需要导入模块
from django.shortcuts import render, HttpResponse, redirect
HttpResponse # 返回字符串类型的数据
render # 返回html页面并支持传值
redirect # 重定向
标签:请求,py,request,django,初识,dict,user,Django
From: https://www.cnblogs.com/wesleyUP/p/16967663.html