django(web框架推导、简介、数据库初识)
一 web框架推导
1 软件开发架构
cs架构
bs架构
bs本质是也是cs
# HTTP协议:无状态,无连接,基于请求,基于tcp/ip的应用层协议 # mysql:c/s架构,底层基于soket,自己封装的协议。mysql的其他客户,navicate(c++图形化界面,实现了请求和响应协议);pymysql(用python语言实现了请求和响应协议) # redis:c/s架构,基于socket,自己封装的协议 # docker:c/s架构,基于HTTP协议,使用restfull规范 # elasticsearch:c/s架构,基于http协议,使用restfull规范
2 纯手撸web框架
# HTTP协议
'''
网络协议
HTTP协议 数据传输是明文
HTTPS协议 数据传输是密文
websocket协议 数据传输是密文 四大特性
1.基于请求响应
2.基于TCP、IP作用于应用层之上的协议
3、无状态
4、短/无链接 数据格式
请求首行
请求头
请求体 响应状态码
1xx
2xx
3xx
4xx
5xx 如何做到后缀的不同返回不同的内容
拿到用户输入的后缀,做判断 不足之处
1、代码重复
2、手动处理http格式的数据,并且只能拿到url后缀,其他数据获取繁琐
3、并发的问题
'''
例:
# 可以将web框架理解成服务端
import socket server = socket.socket() # TCP 三次握手四次握手 osi七层
server.bind(('127.0.0.1', 8080)) # IP协议 以太网协议 arp协议
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
sec-ch-ua: "Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "Windows"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\r\nAccept: 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: document\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n'
'''
while True:
conn, addr = server.accept()
data = conn.recv(1024)
print(data) # 二进制
data = data.decode('utf-8') # 字符串
# 获取字符串中特定的内容 正则 如果字符串有规律也可以考虑用切割
# 直接忽略favicon.ico
conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
current_path = data.split(' ')[1]
# print(current_path)
if current_path == '/index':
# conn.send(b'index ha ha')
with open(r'templates/新闻页面.html', 'rb') as f:
conn.send(f.read())
elif current_path == '/login':
conn.send(b'login ai ai')
else:
conn.send(b'Hello word')
conn.close()
2 借助于wsgiref模块
'''
urls.py 路由和视图函数对应关系
views.py 视图函数(后端业务逻辑)
templates文件夹 专门用来存储html文件
'''
# 按照功能的不同拆分之后,后续添加功能只需要在urls.py书写对应关系然后去views.py书写业务逻辑即可
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(env, response):
'''
:param env: 请求相关的所有数据
:param response: 响应相关的所有的数据
:return: 返回给浏览器的数据
'''
# print(env) # 大字典 wsgiref模块帮你处理好http格式的数据,字典格式
# 从env中获取
response('200 ok', []) # 响应首行 响应头
current_path = env.get('PATH_INFO')
# if current_path == '/index':
# return [b'hello index']
# elif current_path == '/login':
# return [b'hell login']
# return [b'404 error']
# 定义一个变量,存储匹配到的函数名
func = None
for url in urls:
if current_path == url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break # 匹配一个之后,应该立刻结束
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)
'''
会实时监听127.0.0.1:8080地址,只要有客户端来了
都会交给run函数处理(加括号触发run函数的运行)
flask启动源码
make_server('127.0.0.1',8080,obj)
'''
server.serve_forever() # 启动服务端
3 动静态网页
静态网页
页面上的数据是直接写死的,一直不变(不需要数据库操作)
动态网页
数据是实时获取的(就需要进行数据库操作)
ps:
1、后端获取当前时间展示到html页面上
2、数据是从数据库中获取的展示到html页面上
# 动态网页制作
import datetime
def get_time(env):
current_time = datetime.datetime.now().strftime('%Y-%m-%d %x')
# 如何将后端获取的数据“传递”给html文件?
with open(r'templates/03 mytime.html', 'r', encoding='utf-8') as f:
data = f.read()
# data就是一堆字符串(html文件是一对字符串)
data = data.replace('lq', current_time) # 在后端将html页面处理好之后再返回给前端,操作字符串
return data # 后端获取数据库中数据展示到前端页面
# 利用wsgiref模块封装的web框架加上jinja2模板语法,结合前端后端数据库
4 模板语法之jinja2模块
# 将一个字典传递给html文件,并且可以在文件上方便快捷的操作字典数据
pip3 install jinja2
'''模版语法是在后端起作用的'''
from jinja2 import Template def get_dict(env):
user_dic = {'username': 'lq', 'age': 18, 'hobby': 'read'}
with open(r'templates/04 get_dict.html', 'r', encoding='utf-8') as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user=user_dic)
# 给get_dict.html传递了一个值,页面上通过变量名user就能够拿到user_dict
return res # 模板语法(非常贴近python语法)
{{user}}
{{user.get('username')}}
{{user.age}}
{{user['hobby']}} {% for user_dict in user_info %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.password }}</td>
<td>{{ user_dict.hobby }}</td>
</tr>
{% endfor %}
5 借助pymysql实现和数据库链接
import pymysql def get_user(env): # 视图文件中的视图函数
# 去数据库中获取数据,传递给html页面,借助于模版语法,发送给浏览器
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
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() # data_list,列表套字典格式
# print(data_list)
with open(r'templates/05 get_user.html', 'r', encoding='utf-8') as f:
data = f.read()
print(data)
tmp = Template(data)
res = tmp.render(user_info=data_list)
return res
6 自定义简易版本web框架请求流程图
wsgiref模块
1、请求来的时候解析http格式的数据,封装成大字典
2、响应走的时候给数据打包成符合http格式,再返回给浏览器
二 django简介
1 python三大主流web框架
'''
django
特点:大而全,自带的功能特别多
不足之处:
有时候过于笨重
django是一个同步框架,django3.x异步框架 flask
特点:小而精,自带的功能特别少
第三方的模块特别多,越来越来像django
不足之处:
比较依赖第三方的开发者 tornado
特点:异步非阻塞,支持高并发
''' A:socket部分
B:路由与视图函数对应关系(路由匹配)
C:模板语法 django
A用的别人的 wsgiref模块
B用的是自己的
C用的是自己的(没有jinja2好用,但是很方便) flask
A用的是别人的 werkzeug(内部还是wsgiref模块)
B自己写的
C用的别人的(jinja2) tornado
A B C都是自己写的
2 注意事项
# 如何让你的计算机能够正常的启动django项目
1、计算机的名称不能有中文
2、一个pycharm窗口只开一个项目
3、项目里面所有的文件也尽量不要出现中文
4、python解释器尽量使用3.4-3.6之间的版本
(如果你的项目报错,点击最后一个报错信息去
源码中把逗号删除) # django版本问题
1.x 2.x 3.x(直接忽略)
1.x 和 2.x 本身差距不大,以1.x为例
LTS维护时间 # django安装
pip3 install django==1.11.11
如果已经安装了其他版本,无需自己卸载
直接重装,会自动卸载安装新的 验证是否安装成功的方式
终端输入django-admin看看有没有反应
3 django
基本操作
命令行操作
# 命令行操作
1、创建django项目
windows可以先切换到对应的需要建项目存储位置,然后再创建 django-admin startproject mysite mysite文件
manage.py
mysite文件夹
__init__.py
setting.py
urls.py
wsgi.py
# 2、启动django项目
'''
一定要先切换到项目下
cd /mysite
'''
python3 manage.py runserver
http://127.0.0.1:8000/ # 3、创建应用
'''
Next, start your first app by running python manage.py startapp [app_label].
'''
python3 manage.py startapp app01
应用名应该做到见名知意
user
order
web 教学统一用app01/02/03
有很多文件
pycharm操作
# 1、new project 选择左侧第二个django即可
# 2、启动
1)还是用命令行
2)点击绿色小箭头即可
# 3、创建应用
1)pycharm提供的终端直接输入完整命令
python3 manage.py startapp app01
2)pycharm
tools run manage.py task提示
# 4、修改端口号以及创建server
edit confi
4 应用
'''
django是一款专门用来开发app(功能)的web框架
比如淘宝
订单功能
用户相关
投诉相关
创建不同的app对应不同的功能 还比如选课系统
学生功能
老师功能 一个app就是一个独立的功能模块
''' **************创建的应用一定要去配置文件中注册*************
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config', # 全写
'app02', # 简写
]
# 创建出来的应用第一步先去配置文件中注册
ps:在用pycharm创建项目的时候,Pycharm可以帮你创建一个app并且自动注册
5 主要文件介绍
-mysite项目文件夹
--mysite文件夹
--settings.py 配置文件
--urls.py 路由与视图函数对应关系(路由层)
--wsgi.py wsgiref模块(不考虑)
--manage.py django的入口文件
--db.sqlite3 django自带的sqlite3数据库(小型数据库,功能不多有bug)
--app01文件夹
--admin.py django后台管理
--apps.py 注册使用
--migrations文件夹 数据库迁移记录
--models.py 数据库相关的 模型类(orm)
--tests.py 测试文件
--views.py 视图函数(视图层)
6 命令行与pycharm创建的区别
# 命令行创建不会自动有templates文件,需要自己手动创建,而pycharm会自动帮你创建,并且自动在配置文件中配置对应的路径。 # 命令行创建
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
},
] # pycharm创建
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},
] '''
命令行创建django项目的是空,不仅要创建templates文件,还要配置templates文件路径
'DIRS': [os.path.join(BASE_DIR, 'templates')
'''
7 django小白必会三把斧
app应用下面views.py中
from django.shortuts import HttpResonse,render,redirect HttpResponse
返回字符串类型的数据
return HttpResponse('我不想值班,好累') render
返回html文件
return render(request, 'first.html') # setting文件里路径已帮忙设置好 def ab_render(request):
# 视图函数必须要接受一个形参request
user_dict = {'username': 'lq', 'age': 18}
# 第一种传值方式:更加的精准,节省资源
# return render(request, '01 ab_render.html', {'data': user_dict})
# 第二种传值方式:当你要传的数据特别多的时候
# locals会将所在的名称空间中所有的名字全部传递给html页面
return render(request, '01 ab_render.html', locals()) redirect
重定向
return redirect('https://www.xiaomi.com/')
return redirect('/home/') # 跳自己的网址
8 静态文件配置
# 登录功能
html文件默认都放在templates文件下
将网站所使用的静态文件默认都放在static文件夹下 静态文件
前端已经写好了的,能够直接调用使用的文件
网站写好的js文件
网站写好的css文件
网站用到的图片文件
第三方前端框架 拿来就可以直接使用的 # django默认是不会自动创建static文件夹,需要自己手动创建
一般情况下我们在static文件夹内还会做进一步的划分处理
-static
--js
--css
--img
其他三方文件 '''
在浏览器中输入url能够看到对应的资源
是因为后端提前开设了该资源的接口
如果访问不到资源,说明后端没有开设该资源的接口
http://127.0.0.1:8000/static/bootstrap-3.4.1-dist/css/bootstrap.min.css
''' ********************************************************
# 静态文件配置
STATIC_URL = '/static/' # 类似于访问静态文件的令牌 # 要想访问静态文件,必须以static开头
# /static/bootstrap-3.4.1-dist/js/bootstrap.min.js
# /static/令牌
# 取列表里面从上往下依次查找
# bootstrap-3.4.1-dist/js/bootstrap.min.js
# 都没有才报错 # 配置
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
os.path.join(BASE_DIR, 'static1'),
os.path.join(BASE_DIR, 'static2'),
]
# 从上往下找 ********************************************************
当你在写django项目的时候,可能会出现后端代码修改了但是前端页面没有变化的情况
1.你在同一个端口开了好几个django项目
一直在跑的其实是第一个django项目 2.浏览器缓存的问题
settings
network
disable cache 勾线上
******************************************************** # 静态文件动态解析
在html文件中
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js'%}">
# form表单默认是get请求数据
http://127.0.0.1:8000/login/?username=lq&password=123 '''
form表单action参数
1、不写 默认朝当前所在的url提交数据
2、全写 指名道姓
3、只写后缀 /login/ 自动补全ip和端口
''' # 在前期使用django提交post请求的时候,需要取配置文件中注释掉一行代码
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',
]
9 request对象方法初识
request.method # 返回请求方式,并且是全大写的字符串类型 < class 'str'> request.POST # 获取用户POST请求提交的普通数据不包含文件
print(request.POST)
# 字典嵌套列表的格式
# <QueryDict: {'username': ['lq'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
request.POST.get() # 获取列表最后一个元素,获取类型是字符串
request.POST.getlist() # 直接将列表取出,类型是列表 request.GET # 获取用户GET请求提交的普通数据不包含文件
print(request.GET)
# 字典嵌套列表的格式
# <QueryDict: {'username': ['lq'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
request.GET.get() # 获取列表最后一个元素
request.GET.getlist() # 直接将列表取出 '''
GET请求携带的数据是有大小限制的,大概只有4kb左右
POST请求则没有限制
'''
def login(request):
# 返回一个登录界面
'''
get请求和post请求应该有不同的处理机制
:param request: 请求相关的数据对象,里面有很多简易的方法
:return:
'''
# print(request.method) # 返回请求方式,并且是全大写的字符串形式
if request.method == 'GET':
print(request.GET)
# return HttpResponse('收到,宝贝')
# elif request.method == 'POST':
# return HttpResponse('收到,宝贝')
# 推荐写法
if request.method == 'POST':
# 获取用户数据
print(request.POST) # 获取用户提交的post请求数据(不包含文件)
# <QueryDict: {'username': ['lq'], 'password': ['123']}>
# username = request.POST.get('username')
# print(username, type(username)) # lq<class 'str'>
# get只会获取列表最后一个元素,所以获取的值是字符串类型
# hobby = request.POST.getlist('hobby') # 列表
hobby = request.POST.get('hobby') # 字符串
print(hobby, type(hobby))
# getlist 获取的值就是个列表 # 获取用户的用户名和密码,然后利用orm操作数据,校验数据是否正确
username = request.POST.get('username')
password = request.POST.get('password')
# print(password, type(password))
# 去数据库中查询数据
res = models.User.objects.filter()
print(res)
# <QuerySet [<User: User object>]> [数据对象1,数据对象2...],表中的一行一行的数据
user_obj = models.User.objects.filter().first()
user_obj = res[1]
print(user_obj)
print(user_obj.username)
print(user_obj.password, type(user_obj.password))
if user_obj:
# 比对密码是否一直
if password == str(user_obj.password):
return HttpResponse('登录成功')
else:
return HttpResponse('密码错误')
else:
return HttpResponse('用户不存在')
# print(request.GET) # 获取用户提交的get请求数据
# # <QueryDict: {'username': ['lq'], 'password': ['123'], 'hobby': ['111', '222', '333']}>
# hobby = request.GET.get('username')
# print(hobby, type(hobby))
# print(request)
return render(request, 'login.html')
三 数据库
pycharm链接数据库(MySQL)
'''
三个位置查找数据库相关
右侧上方database
左下方database
配置里面的plugins插件搜索安装 再没有,只有卸载pycharm pycharm可以充当很多款数据库软件的客户端
'''
# 需要提前创建好库 # 明明链接上了数据库,但是看不到表无法操作这个时候只需要将刚刚创建的链接删除,重新链接一次即可
django链接数据库(MySQL)
# 默认用的是sqkite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
} # django链接MySQL
1、第一步配置文件中配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day60',
'USER': 'root',
'PASSWORD': '123',
'HOST': '127.0.0.1',
'PORT': 3306,
'CHARSET': 'utf8',
'OPTIONS':{'init_command':'SET sql_mode="STRICT_TRANS_TABLES",storage_engine=INNODB;'} #设置数据库为INNODB,为第三方数据库登录用
}
}
2、代码声明
django默认用得是mysqldb模块链接MySQL
但是该模块的兼容性不好,需要手动改为用pymysql链接 需要告诉django不要用默认的mysqldb,而是用pymysql # 在项目名下的init或者任意的应用名下的init文件中书写以下代码即可
import pymysql
pymysql.install_as_MySQLdb()
Django ORM
*******ORM不会帮你创建库,只能创建到表的层面**********
'''
ORM 叫对象关系映射
作用:能够让一个不会sql语句的小白也能够通过python,面向对象的代码简单快捷的操作数据库
不足之处:封装程度太高,有时候sql语句的效率偏低,需要自己写SQL语句 类 表
对象 记录
对象属性 记录某个字段对应的值
'''
应用下面的models.py文件 # 1.先去models.py中书写一个类(类<--->模型类 表<--->模型表)
class User(models.Model):
# id int primary_key auto_increment
id = models.AutoField(primary_key=True)
# 等价sql语句,username varchar(32)
username=models.CharField(max_length=32)
# 等价sql语句,password int
password=models.IntegerField() *******************2.数据库迁移命令**********************
'''
python3 manage.py makemigrations 将操作记录到(migrations文件夹)
python3 manage.py migrate 将操作真正的同步到数据库中 pycharm简单快捷输入
tools
run manage.py tassk
自动提示
'''
****只要你修改了models.py中跟数据库相关的代码,就必须重新执行上述的两条命令**** class User(models.Model):
# id int primary_key auto_increment
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=32, verbose_name='用户名')
'''
CharField必须要指定max_length参数,不指定会直接报错
verbose_name该参数是所有的字段都有的,就是用来对字段的解释
'''
password = models.IntegerField(verbose_name='密码') class Author(models.Model):
'''
由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段
所以orm不定义主键字段的时候,orm会自动帮你创建一个名为id主键字段
后续在创建模型表的时候,主键字段名没有额外的叫法,那么主键字段可以省略不写
'''
username = models.CharField(max_length=32)
password = models.IntegerField()
字段的增删改查
# 字段的增加
1、可以在终端内直接给出默认值
2、该字段可以为空
info = models.CharField(max_length=32, verbose_name='个人简介', null=True)
3、直接给字段设置默认值
hobby = models.CharField(max_length=32, verbose_name='兴趣爱好', default='study') # 字段的修改
直接修改字段代码然后执行数据库迁移的两条命令即可 # 字段的删
直接注释对应的字段,再执行数据库迁移的两条命令即可
执行完毕后字段对应的数据也都没有了 '''
在操作models.py的时候一定要细心
千万不要注释一些字段
执行迁移命令之前最好先检查一下自己写的代码
'''
数据的增删改查(表中一行一行的数据为对象)
# 查
res=models.User.objects.filter(username=username)
print(res)
# <QuerySet [<User: User object>]> [数据对象1,数据对象2...],表中的一行一行的数据
'''
返回值是一个querySet对象,你先看成是列表套数据对象的格式 [数据对象1,数据对象2....],表中的一行一行的数据
它支持索引取值,切片操作,但是不支持负数索引
同样不支持索引取值
'''
user_obj = res[0]
print(user_obj)
print(user_obj.username)
print(user_obj.password, type(user_obj.password)) # 推荐的取值方式
user_obj=models.User.objects.filter(username=username).first()
# first()对应的就是索引为0的数据对象,在mysql表中,也是取主键值为1的一行数据集合对象
'''
filter括号内可以携带多个参数,参数与参数之间默认是and关系,筛选出那一行数据
可以把filter联想成where记忆
'''
数据的增
# 直接获取用户数据存入数据库,
insert into t1(age,name) values(18,'jason'); # mysql中插入数据 def reg(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 直接获取用户数据存入数据库
# 第一种增加方式
# res = models.User.objects.create(username=username, password=password)
# 返回值就是当前被创建的对象本身
# print(res, res.username, res.password) # 第二种增加方式
user_obj = models.User(username=username, password=password)
user_obj.save()
# 先给用户返回一个注册页面
return render(request, 'reg.html') # 第一种方式增加
from app01 import models
res = models.User.objects.create(username=username, password=password)
# 返回值就是当前被创建的对象本身
print(res, res.username, res.password) # 第二种方式增加
user_obj=models.User(username=username,password=password)
user_obj.save()
数据的查、改、删(实例)
需求:先讲数据库中的数据全部展示到前端,然后给每一个数据两个按钮,一个编辑,一个删除
# 查
def userlist(request):
# 查询用户表里面所有的数据
# 方式一
# data=models.User.objects.filter()
# print(data) # 方式二
user_queryset = models.User.objects.all()
# print(data) # <QuerySet [<User: User object>, <User: User object>]> # return render(request,'userlist.html',{'user_queryset':user_queryset})
return render(request, 'userlist.html', locals())
useerlist.html
<body>
<h1 class="text-center">数据展示</h1>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>password</th>
<th>action</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_queryset %}
<tr>
<td>{{ user_obj.id }}</td>
<td>{{ user_obj.username }}</td>
<td>{{ user_obj.password }}</td>
<td>
<a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
<a href="/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
</td>
</tr> {% endfor %} </tbody>
</table>
</div>
</div>
</body>
流程:
点击userlist.html中的编辑a标签,是用get的方式,通过urls.py中的/edit/到视图函数edit(),根据选择的edit_id,
从数据库中查询到要编辑的数据,展现到edit.html文件中,修改后,点击提交,from表单中的action没有值,
提交的数据的地址任是/edit/,这次是post请求,就把数据传给数据库,并修改,redirect(/userlist/),再执行视图函数
uselist(),查询新的更新后的数据库数据,展示到userlist.html。
# 编辑功能
# 点击编辑按钮朝后端发送编辑数据的请求
'''
如何告诉后端用户想要编辑那一条数据?
将编辑按钮所在的那一行数据的主键值发送给后端
利用url问号后面携带参数的方式
'''
后端查询出用户想要编辑的数据对象,展示到前端页面供用户查看和编辑
def edit(request):
# 获取url问号后面的参数
edit_id = request.GET.get('user_id')
# 查询当前用户想要编辑的数据对象
# edit_obj = models.User.objects.filter(id=edit_id).first()
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 修改数据库中对应的数据内容
# 修改数据方式1
models.User.objects.filter(id=edit_id).update(username=username, password=password)
'''
将filter查询出来的列表中的所有的对象全部更新 批量更新操作
只修改被修改的字段
'''
# 修改数据方式2
# edit_obj.username=username
# edit_obj.password=password
# edit_obj.save()
'''
上述方法当字段特别多的时候效率会非常底
从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改
'''
# 跳转到数据的展示页面
return redirect('/userlist/')
# 查询当前用户想要编辑的数据对象
edit_obj = models.User.objects.filter(id=edit_id).first()
# 返回编辑页面
return render(request, 'edit_user.html', locals())
edit_user.html
<body>
<h1 class="text-center">编辑</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
<p>username:<input type="text" name="username" class="form-control" value="{{ edit_obj.username }}"></p>
<p>password:<input type="text" name="password" class="form-control" value="{{ edit_obj.password }}"></p>
<input type="submit" class="btn btn-info btn-block" value="编辑">
</form>
</div>
</div>
</div>
</body>
# 删除功能
def delete_user(request):
# 获取用户想要删除的数据id值
delete_id=request.GET.get('user_id')
# 直接去数据库中找到对应的数据删除即可
models.User.objects.filter(id=delete_id).delete()
'''
批量删除
'''
# 跳转到展示页面
return redirect('/userlist/')
'''
真正的删除功能应该要二次确认,后面再讲
删除数据内部不是真正的删除,会给数据添加一个标识字段用来表示当前数据是否被删除了,
如果数据被删了仅仅只是将字段修改一个字段
''' username password is_delete
lq 123 0
zd 123 1
django orm
中如何创建表关系
'''
表与表之间的关系
一对多 多对多 一对一
判断表关系的方法:换位思考
'''
图书表 出版社表 作者表 作者详情表
'''
图书和出版社是一对多的关系,外键字段建在多的那一方,book 图书和作者是多对多的关系,需创建第三张表专门储存 作者和作责详情表是一对一
'''
# 创建表关系,先将基表创建出来,然后再添加外键字段
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
# 总共八位,小数点后面占两位
'''
图书和出版社是一对多,并且书是多的一方,所以外键字段放在书表后面
'''
publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联
'''
如果字段对应的是ForeignKey,那么orm会自动在字段的后面加_id
如果加了_id,后面还是会加_id
'''
'''
图书和作者是多对多的关系,外键字段键在任意一方均可,但是推荐在查询频率较高的一方
'''
authors = models.ManyToManyField(to='Author')
'''
authors是一个虚拟字段,主要用来告诉ORM,书籍表和作者表是多对多关系
让ORM自动帮你创建第三张关系表
'''
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
'''
作者与作者详情是一对一的关系,外键字段在任意一方都可以,当时推荐建在查询频率较高的表中
'''
author_detail = models.OneToOneField(to='AuthorDetail')
'''
OneToOneField也会自动给字段加_id后缀
所以也不要在在后面加_id
''' class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=32) '''
ORM中如何定义三种关系
publish = models.ForeignKey(to='Publish')
authors = models.ManyToManyField(to='Author')
author_detail = models.OneToOneField(to='AuthorDetail') ForeignKey
oneToOneField
会自动在字段后面加_id后缀
'''
# 在django1.x版本中外键默认都是级联更新级联删除
# 多对多的表关系可以有好几种创建方式,暂且介绍一种
# 针对外键字段里面的其他参数,暂时不考虑,自己可以百度
django
请求生命周期流程图(必会)
扩展知识
缓存数据库
提前已经将你想要的数据准备好了,你来直接拿就可以
提高效率和响应时间
当你在web页面修改数据时,并没有立刻修改,要等段时间才修改 是因为请求数据还是在访问缓存数据库,没有访问后端数据库
四 虚拟环境(了解)
在正常开发中,我们给每一个项目配备一个该项目独有的解释器环境
该环境只有该项目用到的模块,用不到一概不装
linux缺什么才装什么
虚拟环境
每创建一个虚拟环境就类似于重新下载了一个纯净的python解释器
但是虚拟环境不要创建太多,是需要消耗硬盘空间
扩展:
每一个项目要用到很多模块,能不能一次装好
开发中,给每一个项目配备一个requirement.txt文件
里面书写该项目所有的模块既版本
直接输入一条命令即可一键安装所有模块既版本
创建虚拟环境的步骤,new project---pure python---点击new environment ---点击make available to all projects---create---退出
---setting---interpreter---安装包---django---退出---new project---选择虚拟环境的解释器
五 django
版本''django1.x路由层使用的是url方法
而django2.x和3.x版本中路由使用的是path方法
url()第一个参数支持正则
path()第一个参数是不支持正则,写什么就匹配什么 如果习惯使用path那么再提供另外一种方法
'''
from django.urls import path, re_path
from django.conf.urls import url re_path(r'^index/',views.index)
url(r'^login/',login) # 2.x和3.x版本里的re_path等价一1.x里的url # 虽然path不支持正则,但是它内部支持五种转换器
path('index/<int:id>/', views.index)
# 将第二个路由里面的内容先转成整型,然后以关键字的形式传递给视图函数 def index(request, id):
print(id,type(id))
return HttpResponse('index') '''
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
''' # 除了有默认的五个转换器之外,还支持自定义转换器(了解)
class MonthConverter:
regex='\d{2}' # 属性名必须为regex def to_python(self, value):
return int(value) def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字 from django.urls import path,register_converter
from app01.path_converts import MonthConverter register_converter(MonthConverter,'mon') from app01 import views urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'), ] # 模型层里面1.x外键默认都是级联更新删除的,但是到了2.x和3.x中需要你手动匹配参数
models.ForeignKey(to='Publish') models.ForeignKey(to='Publish',on_delete=models.CASCADE,
on_update=models.CASCADE)
django2.0版的re_path与path,更多详细看下面链接
https://www.cnblogs.com/xiaoyuanqujing/articles/11642628.html
django(web框架推导、简介、数据库初识)的更多相关文章
- 教程:Visual Studio 中的 Django Web 框架入门
教程:Visual Studio 中的 Django Web 框架入门 Django 是高级 Python 框架,用于快速.安全及可扩展的 Web 开发. 本教程将在 Visual Studio 提供 ...
- [oldboy-django][1初始django]web框架本质 + django框架 + ajax
web框架本质 浏览器(socket客户端) - 发送请求(ip和端口,url http://www.baidu.com:80/index/) - GET 请求头(数据请求行的url上: Http1. ...
- web框架推导 wsgiref模块 jinja2模板语法 django框架简介 django基本操作
目录 纯手撸web框架 web框架的本质 手写web框架 存在的问题 基于wsgiref模块 基本介绍 推导流程 代码封装优化 总结 动静态网页 jinja2模块 前端.后端.数据库三者联动 推导流程 ...
- 初识DJango——Web框架
一.Web框架 HTTP特点 1.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST.每种方法规定了客户与服务器联系的类型不同. 由于HTTP协议简单 ...
- django——web框架简介
1.web应用 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件. 应用程序有两种模式C/S.B/S.C/S是客户 ...
- Django web框架-----Django连接本地现有mysql数据库
第一步:win10下载mysql5.7压缩包配置安装mysql,创建数据库或导入数据库 第二步:win10搭建django2.1.7开发环境,创建项目为mytestsite,创建应用app为quick ...
- Django web框架 下载安装 简单项目搭建
什么是web应用? Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件 应用程序有两种模式C/S.B/S.C/S是客 ...
- Django web框架篇:基础
对于web开发者来说,socket是基础.因为Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 对于真实开发中的python web程序来说,一般会分为两 ...
- Django:web框架本质
一,web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 1,自定义web框架 impo ...
- Linux(CentOS7)系统中部署Django web框架
1. 概述 部署django和vue架在逻辑上可以分为web层与数据库层:web前端通过实现了WSGI协议的模块对python代码进行解析,而python代码中则通过特定于数据库的操作接口对数据库进行 ...
随机推荐
- electron、nodejs、typescript、idea 组合开发,安装和配置 以及错误 等 详细说明
1. 创建项目,创建时 选择 nodejs 项目,因为 开发 electron 与 开发 nodejs 基本一致. 2.安装 electron npm i -D electron@beta 看目录 ...
- 吉特日化MES 与周边系统集成架构
作者:情缘 出处:http://www.cnblogs.com/qingyuan/ 关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路 版权声明:本文版权归作者和博客园 ...
- Ubuntu安装PHP和NGINX环境
Ubuntu安装PHP和NGINX环境 介绍 PHP-FPM PHP-FPM 是 PHP FastCGI Process Manager 的缩写,是 FastCGI 进程管理器. PHP-FPM 是基 ...
- NC16619 [NOIP2008]传球游戏
题目链接 题目 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时 ...
- Android上的日志
Android的日志机制和普通的Java项目有一些不一样, 这里记录一下 安卓内建的Log 安卓应用类型(在build.gradle里定义 android {...})的模块, 可以直接引用内建的an ...
- React18 之 Suspense
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:佳岚 Suspense Suspense 组件我们并不陌生 ...
- 【Android 逆向】VM Kali 中 charles 抓android https 协议
1. 虚拟机调成桥接模式(不用选择 复制物理网络链接状态) 2. 虚拟机中 打开 Charles 4. 选择 Proxy ->SSL Proxying Settings 1. 选择SSL Pro ...
- Java - 将TXT文本文件转换为PDF文件
与TXT文本文件,PDF文件更加专业也更适合传输,常用于正式报告.简历.合同等场合.项目中如果有使用Java将TXT文本文件转为PDF文件的需求,可以查看本文中介绍的免费实现方法. 免费Java PD ...
- 进程,join的使用,守护进程---day30
1.进程 # ### 进程 import os,time #当前进程id(子进程) res = os.getpid() print(res) #1772 #当前进程id(父进程) res = os.g ...
- 1-Django框架简介以及基本操作
安装 注意:安装的磁盘目录,以及后续通过Django创建目录的时候,不要出现中文,否则会出现预料之外的错误 建议:禁止套娃,即不要在A项目中创建B项目 # 如果不指定版本号,默认最新版 pip ins ...