django基础操作简述
django基础操作简述
本文是对django整体架构功能的简单叙述,重在能够通过django架构简单的实现前端网页到后端数据库整体流程的实现,也是对django配置的概念补充。
静态文件
static文件夹 --- 存一些css,js,img,第三方模块等,也可以再分文件夹
如:我们可以要引入本地的bootstrap的css和js文件,那么就可以放在static文件夹中,并且引入到html文件中进行使用,如图:
<link rel="stylesheet" href="static/bootstrap-5.1.3-dist/css/bootstrap.css"> <script src="static/bootstrap-5.1.3-dist/js/bootstrap.bundle.js"></script>
但是当我们访问网页,发现我们预设的bootstrap的样式并没有加载出来
检查一下网络请求,发现是因为bootstrap的css文件和js文件没能正常请求到:
默认情况下无法访问我们这些静态文件,因为没有开放资源连接。
静态文件资源开放
我们的html文件页面是通过url路由文件来配置路由和视图的对应关系,但是,对于繁杂的静态文件而言,使用urls去一个个的配置又过于麻烦,所以针对静态文件,django提供了一种配置接口:
# settings.py 中大概底端的位置
STATIC_URL = '/static/' # 访问静态文件资源的接口前缀
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
] # 存储静态文件资源的目录
配置好后我们再次访问我们的网页,发现bootstrap文件就正常被导入了。
我们还可以让静态文件配置的动态加载,让访问的接口随配置的变化而变化。
在编写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>
这些在html中插入{% %}
形式的占位符,可以配合python代码,在处理这些文字时,实现一些逻辑,这个在后续会有详细的说明。
而这段代码中,导入了静态接口的前缀,让我们的bootstrap文件的请求网址能够随访问的接口前缀变化而变化。
form表单
action:三种情况
-
""
没有写,则默认提交给当前页面所在的地址
-
"https//:一个完整网址"
那就提交给这个指定的网址
-
"/路由" 如:
"/home/"
一定会引到https//:顶级域名/home/
朝当前服务端的对应路由提交
-
"一个字符串" 如:
"home/"
则会引到https//:顶级域名/当前页面路由/home/
相对于现在界面的网址,再向后拼接这个字符串
method:get\post请求方式
-
get请求是最常用的请求方式,是默认的请求方式
这种请求方式,有时会在网址和路由后携带数据,格式为:
?键=值&键2=值2。。
- 这种数据可以通过表单设置method为get提交,也可以直接在网址后提交。
- get所携带的数据大小是有限的。
-
post请求的数据在请求头中
- 这种请求方式,会隐藏的提交数据到后端,因为get请求提交的数据可以被看到不能满足所有的数据提交情况,如提交一些敏感数据时,可能被看到。
- 这种数据可以通过表单提交(method="post")
- post所携带的数据大小是没有限制的。
而post所携带的数据,和get所携带的数据在request对象的不同属性中
request对象
request对象是在wsgiref模块的request字典基础上,又进一步的将其封装成了对象,不但处理了数据,还提供了一些功能。
以下就是针对请求体的一些方法。
属性 | 属性值|方法 | 说明 |
---|---|---|
.method | 获取请求方式 | GET或者POST的字符串 |
.POST | 拿到请求体中的数据 | 拿到post请求携带数的据组织的queryDict |
.GET | 拿到请求首行中的数据 | 拿到get请求携带的数据组织的queryDict |
QueryDict | 可以通过get(),getlist()拿值 | 字典的派生类的对象 |
request.GET # 获取get请求携带数据,组织形式为QuerySet{"":['',],}
# get数据需要
request.POST.get(key) # 获取列表的最后一个数据值
request.POST.getlist(key) # 获取整个列表数据
ps:在表单无法提交(403 forbidden)时,可以在配置中修改以下配置来解决:
Django连接数据库
- Django配置文件中默认配置的是sqlite3,用于本地测试,一般项目都不会用,实际项目中会替换掉。
# 默认配置文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
↓↓↓↓↓↓↓↓
# 修改配置文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # django后端数据引擎
'NAME': 'navicat_test1', # mysql这个属性用数据库即可
'HOST': '127.0.0.1', # ip
'PORT': 3306,
'USER': 'root', # mysql用户名,当然一般的项目中你都不是root
'PASSWORD': '111',
'CHARSET': 'utf8'
}
}
配置文件改完后,看服务端的运行情况,报错了,并提示MySQLdb模块加载错误,是否下载mysqlclient。
我们下载后就恢复正常了,正常的启动我们的服务端。
ps:对于Django1.x版本而言,是通过pymysql连接的,需要以下语句俩配置
import pymysql 换行 pymysql.install_as_MySQLdb()
我们知道数据库能存储的数据类型是有限的,我们如果想要存储我们的类和对象,怎么做呢?
或者说如何通过操作对象的方式去取我们数据库的方式(绕过sql语句)
ORM
将类和对象映射为数据库的数据:
- 类 --- 表
- 对象 --- 记录
- 对象的属性值 --- 记录某个字段的值
orm高度的封装了我们的sql语句,所以查询速度等级并不高,有些时候还是需要自己写sql。
但是orm操作对python程序员方便快捷。
orm操作
类相关
- models.py中编写模型类
from django.db import models
# Create your models here.
class GirlsInfo(models.Model):
# 字段名 = 字段类型 + 约束条件
id = models.AutoField(primary_key=True) # 主键类型
name = models.CharField(max_length=32) # 字符字段
age = models.IntegerField() # 整型字段
-
执行数据库迁移相关命令(每次修改和增加模型类都需要执行)
python38 manage.py makemigrations # 记录数据库相关 python38 manage.py migrate # 将操作同步到数据库 # 第一次会创建很多表、其中一个是当前新增的模型表
记录数据库,django项目会根据models.py的改动同步到app各自的migrations文件夹中。
数据库记录完后,migrate命令会根据migrations记录,将模型类同步到mysql中(创建对应的表)
而对应的表的表名是以app名_类名
来命名的。
除此以外,初次创建表还会建立很多其他的表。
对象相关
- 对 对象记录 进行筛选增删改查
from app02 import models # 将模型类导入
models.类名.objects.create() # 根据字段塞关键字参数,就能插入记录
models.类名.objects.filter() # 筛选并默认查询
models.类名.objects.update() # 批量更新,一般搭配filter使用
models.类名.objects.delete() # 批量删除,一般搭配filter使用
django请求生命流程图
django项目所搭建的网页,从网页输入网址开始,都经历了哪些环节最终响应到我们的浏览器显示出来。一个大致的流程是这样的:
其中需要注意的是,wsgiref和uwsgi都是实现web服务网网关协议的功能模块,都遵循WSGI协议。
而两者的区别在于wsgiref能够承受的并发量很低,只能用于本地测试,而实际的项目中肯定会切换成并发量更高的uwsgi模块
后续的博文会基于这个流程图,分别对每一层进行详细的叙述。
数据增删改查app搭建实操
建立django项目和app
在pycharm中创建新django项目,可以自动生成一个app -- table_crud(自动配置app)
并设置一些基本配置,
- 如templates的路径(TEMPLATES的DIRS)
- 设置可post请求(MIDDLEWARE中间行注释掉)
与数据库建立联系
修改DATABASES配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "site02", # 前提有这个库
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '111',
'CHARSET': 'utf8'
}
}
在models创建模型类
class UserData(models.Model):
id = models.AutoField(primary_key=True) # 如果不写,则会自动生成
name = models.CharField(max_length=32) # 默认varchar,必须指定最大长度
password = models.CharField(max_length=32) # 存个密码便于拓展
age = models.IntegerField()
tel = models.CharField(max_length=32, unique=True) # 电话号码设置个唯一属性
将改动同步到migrations和数据库
python38 manage.py makemigrations
python38 manage.py migrate
确认下migrations文件夹和数据库中是否添加了相应的文件和表。
编写首页
首页主要用来展示我们的数据,并且提供 增加|修改|删除数据 的按钮链接。
总体需要搭建成这样(图中的数据是预设的):
总体搭建首页需要协同路由层,视图层数据处理,html模板语法。
- 首页url配置:
from table_crud import views as table_crud_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', table_crud_views.show_data_page), # 顶级域名默认首页
path('home/', table_crud_views.show_data_page), # 写了home路由也是首页
]
-
视图层
from table_crud import models # 将模板类导入 def show_data_page(request): user_data_list = models.UserData.objects.filter() # 对表进行查询操作 # 将表的查询结果[{},{},{}]通过render提交给html做模板语法,处理完后返回给用户 return render(request, "show_data_page.html", {"user_data_list": user_data_list, })
首页模板
这里有些内容是后续过程中添加的,第一次编写首页时,我们只需要将重点放在:
循环生成行标签,每行插入要展示的用户数据和即可,链接标签可以暂时为空。
<head>
<!--head中导入jQuery、bootstrap等-->
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h1 class="text-center">数据展示页</h1>
<p>
<a class="btn btn-success" href={% url "add_func" %}>添加数据</a>
</p>
<div class="shadow"><table class="table table-striped table-hover">
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>tel</th>
<th>operation</th>
</tr>
</thead>
<tbody>
{% for user_dict in user_data_list %} <!--模板语法循环开始-->
<tr>
<td>{{ user_dict.name }}</td> <!--模板语法:字典可以点取值-->
<td>{{ user_dict.age }}</td>
<td>{{ user_dict.tel }}</td>
<td>
<a class="btn btn-primary btn-sm" href="{% url 'modify_func' user_dict.id %}">修改</a>
<!--模板语法:动态路由解析-->
<a class="btn btn-danger btn-sm delete_btn" href={% url "delete_func" user_dict.id %}>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
<!--绑定事件给删除按钮,如果确认框选择取消,则阻断重定向-->
$('a.delete_btn').click(
function () {
return confirm("你是否确定删除数据")
}
)
</script>
</body>
</html>
编写创建数据页
创建数据页会跳转到一个类似于注册界面的页面,我们可以通过表单标签从前端获取数据,然后通过模型类语句向表中插入新的数据。
依然需要路由层、视图层、模板层协同:
-
路由配置
[path('add_func/', table_crud_views.add_func, name='add_func'),] # 起个别名
-
视图函数
def add_func(request): # 如果是post请求则说明是注册信息,我们就用模型类语法添加数据 if request.method == 'POST': name = request.POST.get("name") password = request.POST.get("password") age = request.POST.get("age") tel = request.POST.get("tel") models.UserData.objects.create(name=name, password=password, age=age, tel=tel) # 添加完数据后,我们可以返回首页 return redirect("http://127.0.0.1:8800") # 如果是get请求,那么拿到添加数据界面 return render(request, "add_data_page.html")
-
前端界面
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h1 class="text-center">数据注册页</h1>
<form action="" method="post">
name:<input name="name" type="text" class="form-control">
password:<input name="password" type="password" class="form-control">
age:<input name="age" type="text" class="form-control">
tel:<input name="tel" type="text" class="form-control">
<br>
<input type="submit" value="提交" class="btn btn-success form-control">
</form>
</div>
</div>
</div>
</body>
编写数据修改页
编写数据修改页时,我们应该是基于原本的数据进行修改,那么在进入相似的编辑页面时,我们应该对编辑界面做一些参数的区分,可以通过
-
路由后跟?携带数据的方式,通过request.GET参数进行区分
-
动态路由+反向解析的方式,让不同记录所对应的编辑链接的路由有区别
而urls动态解析可以捕捉不同的地方,将其作为参数传入视图函数。
我们选择第二种方式,则需要这么编写:
-
路由层
# 在模板中通过模板语法,可以根据记录的id号拼路由,间接传入视图函数 [path('modify/<str:modify_id>/', table_crud_views.modify_func, name='modify_func'),]
-
视图层
def modify_func(request, modify_id): if request.method == 'POST': name = request.POST.get("name") password = request.POST.get("password") age = request.POST.get("age") tel = request.POST.get("tel") # 通过传入的函数modify_id可以对对应的数据进行精准修改 models.UserData.objects.filter(id=modify_id[0]).update(name=name, password=password, age=age, tel=tel) return redirect("http://127.0.0.1:8800") user_dict = models.UserData.objects.filter(id=modify_id)[0] return render(request, 'modify_data_page.html', {"user_dict": user_dict})
-
模板层
几乎和注册一致
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>modify_page</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h1 class="text-center">数据修改页</h1>
<form action="" method="post">
name:<input name="name" type="text" class="form-control" value={{ user_dict.name }}>
password:<input name="password" type="password" class="form-control" value={{ user_dict.password }}>
age:<input name="age" type="text" class="form-control" value={{ user_dict.age }}>
tel:<input name="tel" type="text" class="form-control" value={{ user_dict.tel }}>
<br>
<input type="submit" value="提交" class="btn btn-success form-control">
</form>
</div>
</div>
</div>
</body>
</html>
删除层就不展开讲了,几乎一致。