python-Django框架学习-06

1 Django路由Path方法

1.1 初识path()方法

path 函数来进行路由的匹配,可通过以下方式进行导入:

python 复制代码
#新的2.x版本导入path,导入简化
from django.urls import path
#原来的1.x版本url方式,conf子包
from django.conf.urls import url

但是之前的 url 模块并没有废止,只是 Django 强烈建议我们使用新模块 path 进行路由的匹配。

1.1.1 path方法函数定义

path 函数在 Django中的的定义如下所示:

scss 复制代码
path(route, view, kwargs, name)

它可以接收 4 个参数,其中前两个是必填参数后两个为可选参数。参数解析如下:

  • route:是一个匹配 URL 的准则(类似正则表达式)。当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项,然后执行该项映射的视图函数或者 include 函数分发的下级路由,因此,url 路由的编写在 Django中十分的重要!
  • view:指的是处理当前 url 请求的视图函数。当 Django 匹配到某个路由条目时,自动将封装的 HttpRequest 对象作为第一个参数,被"捕获"的参数以关键字参数的形式,传递给该条目指定的视图函数。
  • kwargs:指使用字典关键字传参的形式给关联的目标视图函数传递参数。
  • name:给 URL 起个别名,常用于 url 的反向解析,避免在模板中适应硬编码的方式使用嵌入 url,在后续章节会进行详细讲解。

当使用 path 方法关联视图函数时与 url 方法相比更为简化,也更容易让初学者理解。

path 方法引入了类型转化器(converter type)的概念,以此省去了较为复杂的正则表达式匹配路由的方法。

实例说明如下:

python 复制代码
#1.x url方法
url(r'^test/(?P<year>[0-9]{4})/$', views.year_test),
#2.x path方法
path('test/<int:year>/', views.year_test),

int 支持整数类型的转化,在上述的例子中, year_test 函数接收到的 year 参数就变成整数而不是字符串,从而避免在视图中使用 year=int(year)。

path 函数定义的<int:year>规则会捕获到 URL 中的值,映射给视图中的同名参数 year ,并根据转换器将参数值转换为指定的类型,这里对应 int 大于等于 0 的整数。

之所以使用转化器,有以下两个原因:

  • 第一是可以将捕获到的字符值转换为对应的类型;
  • 第二是对 URL 中传值的一种限制,避免视图处理出错;

在使用 url 函数时候,我们遇上这样一种情景:即不同的视图函数使用相同的字段作为参数,那么 url 函数也会使用相同正则表达式,只是它们关联的视图函数不同,但是当这个被关联的字段更改的是后,那么可想而知,我们也需要修改所有的正则表达式,重新匹配它,举例如下:

python 复制代码
#views.py 视图函数
def year_test(request, year):
    year = int(year) # 转换整形

urls.py 中配置路由如下所示:

ini 复制代码
from django.conf.urls import url #引入url方法
urlpatterns = [
    url('test/(?P<year>[0-9]{4})/', year_tst),
    url('test/(?P<id>[a-zA-Z0-9]+)/num/', num_view),
    url('test/(?P<id>[a-zA-Z0-9]+)/num1/', num1_view),
    url('test/(?P<id>[a-zA-Z0-9]+)/num2/', num2_view),
]

利用 path 方法中提供的类型转换器就很好的解决了这一问题。

1.2 path方法类型转化器

Django 默认支持 5 个类型转换器,在大多数情况下,绝对可以满足我们的正常业务需求,如果不能,Django 同样提供了自定义转换器。

下面介绍 Django 默认支持的转换器,如下所示:

  • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式;
  • int,匹配正整数,包含0;
  • slug,匹配字母、数字以及横杠、下划线组成的字符串;
  • uuid,匹配格式化的 uuid,如 075194d3-6885-417e-a8a8-6c931e272f00;
  • path,匹配任何非空字符串,包含了路径分隔符。

1.3 re_path正则表达式匹配

Django 2.x 之后也支持我们使用正则表达式来捕获值,在这里需要使用 re_path(),而不是前面介绍的 path()。我们使用带命名的正则表达式分组,语法如下:

css 复制代码
(?P<name>pattern) 

其中,尖括号里的name为分组名,pattern为正则表达式。re_path()同样包含于django.urls模块中,所以同样使用如下方式进行导入。示例如下:

python 复制代码
from django.urls import path, re_path  #导入re_path
from . import views
urlpatterns = [
    re_path('test/(?P<year>[0-9]{4})/', views.year_test),
    re_path('test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_test)]

2 Django实现数据插入

我们之前利用 Model 模型类创建了 index 应用所需的三张数据表,在本节我们介绍如何实现在 Django 项目中创建 Model 的实例对象,即向数据表中插入数据。

2.1 save方法创建Model实例

在 cmd 命令行进入项目 manage.py 目录下,然后使用如下命令进入 Django shell 环境。

复制代码
python manage.py shell 

然后创建 Model 实例,使用 save() 方法保存数据,如下所示:

ini 复制代码
from index.models import Book #导入相关model类
#创建Book实例化对象
book=Book(title="Python",public="清华出版社",price="80.00",retail_price="80.00")
book.save()# 调用save方法进行保存
book=Book(title="Flask",public="图灵出版社",price="30.00",retail_price="30.00")
book.save()# 调用save方法进行保存
book=Book(title="Django",public="北大出版社",price="50.00",retail_price="50.00")
book.save()# 调用save方法进行保存

最后调用 save 方法进行保存。通过上述代码,我们就在数据库中添加了三条有关书籍的记录。

创建 Book 实例,其实就是填充有关 Model 实例的各个字段,如果设置了默认值或者有允许为 null 的字段可以不填,最后调用 save() 保存实例(该方法没有返回值)。在 save() 执行以后,Django 会将 book实例化数据保存到数据库中。

注意,每创建一条数据都需要调用一次 save() 方法。

2.2 create方法创建Model实例

除了以上方法外,我们也可以使用模型管理器对象提供的 create() 方法,使用方法如下所示:

ini 复制代码
Book.objects.create(title="Java",public="北大出版社",price="30.00",retail_price="30.00")

然后继续插入如下数据:

ini 复制代码
Book.objects.create(title="MySQL",public="北大出版社",price="35.00",retail_price="35.00")
Book.objects.create(title="C#",public="北大出版社",price="45.00",retail_price="40.00")
Book.objects.create(title="Redis",public="北大出版社",price="25.00",retail_price="25.00")

这种创建 Model 实例对象的过程比较简单,create 执行之后就在数据库中插入了一条记录,这也是我们推荐使用的方法。

最后访问数据库可以看到最新插入的数据记录:

3 Django查询数据库操作详解

在 web 开发过程中,Django 与后台数据库的交互是必不可少的一项,也是实现业务逻辑所需数据的重要方式,所以 Django 的表查询操作就显的尤为重要。在本节我们将全面阐述 Django 的表查询 API。本节知识属于重中之重,希望各位小伙伴能够尽可能的掌握这些 API,懂得活学活用,熟悉每个 API 的使用场景,这将对后续学习 Django 框架有很大的帮助。

3.1 返回单条查询结果

3.1.1 使用get查询

因为 get 查询可能会抛出异常,所以若在项目使用 get 查询的时,经常会与 try..except 异常处理语句一起使用。示例如下:

ini 复制代码
from index.models import Author
Author.objects.create(name="Tom",email="[email protected]")
Author.objects.get(name="Tom")

如果执行两次下面的语句,就会有两个Tom

Author.objects.create(name="Tom",email="[email protected]")

此时执行 Author.objects.get(name="Tom") 会报错

3.1.2 使用get_or_create查询

该方法的查询过程与 get 类似,都需要传递查询参数,但是不 get 不同的是,它返回值是一个 tuple 对象,通过举例子来说明。

ini 复制代码
Author.objects.get_or_create(name="Xiaolong")#先查询是否存在若不存在则新建该实例对象

元组中的第一个元素代表实例对象,第二个元素是布尔值,标识返回的实例对象是否是新创建的,其中 True 代表新建实例对象,False 代表原有实例对象。

3.2 原生数据库操作方法

所谓原生数据库操作即使用 SQL 语句来进行数据库的相关的查询操作。

那你可能会问,Django 已经有 ORM 了,为什么还会提供原生语句的操作呢?

其实这个问题也很容易想明白,ORM 虽然为我解决了大部分的有业务场景,但是对于复杂的查询来说,ORM 还是有点力不从心,有时无法满足开发者的要求或者书写起来比相较 SQL 语句来说很麻烦,那么在这个时候使用原生 SQL 语解决问题就是不错的选择。

在 Django 中,可以使用模型管理器(Marager)的 raw 方法来执行 select 语句进行数据的查询。raw 方法的返回值是一个 RawQuerySet 对象,该对象支持索引和切片,同样也可以对它进行迭代得到 Model 实例对象。但是,与 QuerySet 不同的是,它不能执行 fillter、exclude 等方法。下面通过举例说明 raw 方法如何使用。

3.2.1 raw方法语句格式

使用raw方法的语法格式如下所示:

arduino 复制代码
MyModel.objects.raw('sql语句')

3.2.2 raw方法查询实例

添加如下代码在index\views.py 中:

python 复制代码
def BookName(request):
    books=Book.objects.raw("select * from index_book") #书写sql语句
    return render(request,"index/allbook.html",locals())

在 templates\index 中创建 allbook.html,代码如下:

erlang 复制代码
{% for book in books %}
<p>{{book.title}}</p>
{% endfor %}

最后配置路由。

通过访问 127.0.0.1:8000/index/allbook/,可以得到所有书籍的 title。

3.2.3 游标cursor执行SQL语句

那么执行非查询语句呢?如何使用原生的 SQL 语句呢? Django 提供了游标 cursor 对数据库进行增删改操作,在 Django 中执行非查询语句必须使用游标进行操作。游标 cursor 定义在 django.db.connection 包中,使用前用下面的方式进行导入:

javascript 复制代码
from django.db import connection

用创建 cursor 类的构造函数创建 cursor 对象,再使用 cursor 对象执行 SQL 语句。为确保能够在出现异常时释放 cursor 游标,通常使用 with 语句进行创建操,如下所示:

javascript 复制代码
from django.db import connection
with connection.cursor() as cur:
    cur.execute('执行SQL语句')

使用示例如下:

python 复制代码
from django.db import connection
with connection.cursor() as cur:
#调用游标对象的execute方法,更新author的名字
cur.execute('update index_author set name="Jack" where id=3;')
with connection.cursor() as cur: 
# 删除id为3的一条author记录 
cur.execute('delete from index_author where id=3;')

虽然 Django 提供了 raw SQL的查询方法以及 cursor 游标对象的使用,但是它们很少的被使用,应为这些方法都需要考虑不同数据库的不同特性。Django 官网建议我们尽量使用 ORM 模块来完成相关操作。

相关推荐
电院工程师6 分钟前
SM3算法Python实现(无第三方库)
开发语言·python·算法·安全·密码学
白露与泡影16 分钟前
springboot + nacos + k8s 优雅停机
spring boot·后端·kubernetes
菜鸟谢34 分钟前
windows xp 下载 sp0 sp1 sp2 sp3 sp4
后端
CodeDevMaster36 分钟前
在Jupyter Notebook中使用Conda虚拟环境
python·jupyter
AirMan36 分钟前
你真的懂 MySQL 的一致性读和当前读的区别吗?
后端·面试
David爱编程42 分钟前
容器性能优化实战指南——防止“吃爆”服务器就靠这些招!
后端·docker·容器
Android洋芋1 小时前
GitHub项目部署的终极指南:从零到一掌握Docker实战
后端
冷月半明1 小时前
告别手动拖动!Python+dddocr自动化破解多缺口滑块
python
Kusunoki_D1 小时前
Python 实现 Web 静态服务器(HTTP 协议)
服务器·前端·python
林太白1 小时前
Next.js超简洁完整篇
前端·后端·react.js