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="456789@163.com")
Author.objects.get(name="Tom")

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

Author.objects.create(name="Tom",email="456789@163.com")

此时执行 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 模块来完成相关操作。

相关推荐
小白~小黑几秒前
软件测试基础二十(接口测试 Postman)
python·自动化·postman
codists几秒前
《Django 5 By Example》阅读笔记:p76-p104
python·django·编程人
欧阳枫落9 分钟前
python 2小时学会八股文-数据结构
开发语言·数据结构·python
天天要nx13 分钟前
D64【python 接口自动化学习】- python基础之数据库
数据库·python
monkey_meng20 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss28 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
feifeikon1 小时前
Python Day5 进阶语法(列表表达式/三元/断言/with-as/异常捕获/字符串方法/lambda函数
开发语言·python
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
她说彩礼65万1 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc
陈随易1 小时前
农村程序员-关于小孩教育的思考
前端·后端·程序员