摘要
通过Django框架设计一个商城网站,为了记忆其中的关键设置要点,同时对项目的重要知识点进行回顾记忆加深,通过笔记的形式进行记录方便记忆学习。
一、商城的路由
1、路由的分发规则
首先一个完整的路由包含:路由地址、视图函数(或者视图类)、路由变量和路由命名。其中基本信息必须有:路由地址和视图函数(或者视图类),路由地址即我们常说的网址;视图函数即项目应用(App)的views.py文件所定义的函数或类;一般默认情况下,设置路由地址是在项目同名的文件夹urls.py文件里实现的,这也是由配置文件settings.py的ROOT_URLCONT决定(一般都是指定项目文件的urls.py)。
一个项目当中可能会存在多个项目应用(App),如果项目的所有路由地址都在项目下的urls.py中定义,当项目规模越来越大的时候,项目下的urls.py定义的路由地址就会越来越多,从而造成难以管理的局面。为了更好的区分项目应用的(App)路由地址,我们在项目文件夹下的urls.py下为不同的项目应用(App)定义一条路由入口进行路由分发。首先应该在不同应用(App)下手动去创建一个urls.py文件。
然后我们在总项目文件下打开urls.py,将各个项目应用下面的urls.py添加进去,添加方法由Django内置函数path和include实现,详细代码如下:
from django.contrib import admin
from django.urls import path, re_path, include
from django.conf import settings
from django.views.static import serve
urlpatterns = [
path('admin/', admin.site.urls),
# 添加项目应用index、commodity、shopper的urls.py
path('', include(('index.urls', 'index'), namespace='index')),
path('commodity', include(('commodity.urls', 'commodity'), namespace='commodity')),
path('shopper', include(('shopper.urls', 'shopper'), namespace='shopper')),
# 配置媒体资源的路由信息
re_path('media/(?P<path>.*)', serve,
{'document_root':settings.MEDIA_ROOT}, name='media'),
]
上面文件夹里面定义了五条路由信息,第一条是路由信息,后面三条是注册应用路由信息,最后一条是媒体资源地址。path('路由地址/', ‘指向文件的地址’)。
- path('', include(('index.urls', 'index'), namespace='index')):其中路由地址为'/',即127.0.0.1:8000,通常是网站的首页;路由函数include将路由地址分发给index的urls.py处理。
- path('commodity', include(('commodity.urls', 'commodity'), namespace='commodity')):同理,路由地址为'/commodity',即127.0.0.1:8000/commodity,路由函数include将路由地址分发给commodity的urls.py处理。
- path('shopper', include(('shopper.urls', 'shopper'), namespace='shopper')):和上面同理。
- re_path('media/(?P
.*)', serve, {'document_root':settings.MEDIA_ROOT}, name='media'):路由地址为'/media/xxx',即127.0.0.1:8000/media/xxx,这是媒体资源的路由地址,路由函数re_path则是表示允许在路由地址中设置正则表达式。
将路由进行分发规则设置完成以后,运行Django项目会将路由进行分发处理,规则如下:
(1)当运行Django项目的时候,首先Django会从项目主文件夹下urls.py找到各个项目应用(App)的urls.py,然后读取每个项目应用(App)的urls.py定义的路由信息,从而生成完整的理由列表。
(2)用户在浏览器当中访问某个路由地址时,Django就会收到该用户的请求信息。
(3)Django从请求信息当中获取路由地址,并在路由列表当中匹配相应的路由信息,再执行路由信息所指的路由函数(或者视图类),从而完成整个请求响应过程。
2、路由分发详解
路由函数include设有参数arg和namespace,参数arg指向项目应用App的urls.py文件,其数据格式以元组或者字符串表示;可选参数namespace是路由的命名空间。想要对路由设置参数namespace,则参数arg必须以元组格式表示,其中元组长度为2。以路由path('', include(('index.urls', 'index'), namespace='index'))为例子,参数arg为('index.urls', 'index'),参数每个元素的说明如下:
- 第一个元素是项目应用的urls.py文件,比如('index.urls', 'index')的'index.urls',这是代表着项目应用index的urls.py文件。
- 第二个元素可以自行命名,但是不能为空,一般情况以项目应用(App)命名。
注:如果设置了namespace但是参数arg元组长度不足2的时候,运行Django就会抛出错误。
路由函数include的作用是将当前路由分配到某个项目应用的urls.py文件,而项目应用的urls.py可以设置多条路由,类似计算机上的文件夹A,下面包含多个子文件夹,而Django的namespqce相当于对文件夹A进行命名。Django的命名空间namespace可以为我们快速定位某个项目应用urls.py,再结合路由命名就能快速找到某条路由的具体信息。
3、项目的路由地址
首先对商城网站首页的路由地址进行定义,定义方法代码如下:
from django.urls import path
from .views import * # 导入当前文件下views文件夹下的所有视图函数或者类
# from index import views
# from index.views import *
urlpatterns = [
path('', indexView, name='index')
]
(1)首先上面的path函数中第一个参数为空字符串,这是表示具体的路由地址127.0.0.1:8000。
(2)第二个参数为indexView,这是指向项目应用index的views.py的每个indexView名称的视图函数或者视图类,当用户在浏览器访问127.0.0.1:8000的时候。Django接收到一个HTTP请求,从请求中获取路由地址并与自身的路由列表进行匹配,如果路由地址匹配成功,Django将HTTP请求交给路由地址指向的某个视图函数或者视图类进行业务处理。
(3)第三个参数name='index',这是函数path的可选参数,该参数是命名路由地址,实际开发当中必须为每个路由地址进行命名,可以在视图或模板中使用路由名称生成相对应的路由地址。
下一步对项目的commodity的路由地址进行定义,定义方法如下:
from django.urls import path
from .views import *
urlpatterns = [
path('.html', commodityView, name='commodity'),
path('/detail/<int:id>.html', detailView, name='detail')
]
上面代码分别定义两条路由地址,路由地址的说明如下:
(1)项目应用commodity的urls.py的路由空间是path('commodity', include(('commodity.urls', 'commodity'), namespace='commodity')),因此路由commodity为127.0.0.1:8000/commodity.html,路由detail为127.0.0.1:8000/commodity/detail/id.html。
(2)路由detail设置了路由变量id,该变量以整数型表示,它可以代表1、2、3········等整数,变量id对应商品信息表的主键id,通过改变id的数值可以查看不同商品的详细介绍。
(3)路由地址末端设置了'.html',这是一种伪静态URL技术,可将网址设置为静态网址,用于SEO搜索引擎的爬取(更快提升自然排名),如百度、谷歌等。此外在末端设置'.html'是为变量id设置终止符,假如末端没有设置'.html',并且路由变量为字符串类型,在浏览器上输入无限长的字符串,路由也能正常访问。
最后定义shopper的路由地址,在该文件夹定义个人中心页、购物车信息页、用户登录注册和用户注销的路由地址,代码如下:
from django.urls import path
from .views import *
urlpatterns = [
path('.html', shopperView, name='shopper'),
path('/login.html', loginView, name='login'),
path('/logout.html', logoutView, name='logout'),
path('/shopcart.html', shopcartView, name='shopcart'),
]
上述代码定义4条路由地址,每个路由多对应的功能说明如下:
(1)路由shopper代表的是个人中心页,它的路由地址是path('shopper', include(('shopper.urls.py', 'shopper'), namespace='shopper')),因此路由地址是127.0.0.1:8000/shopper.html,个人中心页的业务逻辑由项目应用shopper的views.py定义的视图函数shopperView实现。
(2)路由login代表的用户登录注册页,路由地址为127.0.0.1:8000/shopper/login.html,他的业务逻辑由项目应用的shopper的views.py定义的视图函数loginView实现。
(3)路由logout实现个人中心的用户注销功能,路由地址为127.0.0.1:8000/shopper/logout.html,他的业务逻辑由项目应用shopper的views.py定义的视图函数logoutView实现。
(4)路由shopcart代表购物车信息页,路由地址为127.0.0.1:8000/shopper/shopcart.html,他的业务逻辑由项目应用shopper的views.py中定义的shopcartView实现。
4、路由的定义规则
(1)每个urls.py文件的路由地址必须在列表urlpatterns里定义,换句话说,每个urls.py中必须设有一个列表urlpatterns,该列表是用于定义路由信息。
(2)每条路由是由函数path定义,函数path设置了3个参数:第一个参数是设置具体的路由地址;第二个参数是指向项目应用的views.py的某个视图函数或者视图类,负责处理路由的业务逻辑;第三个参数为name='index',这是函数path的可选参数,该参数是命名路由地址。
(3)如果函数path第二个参数使用内置函数include,该路由是实现路由分发功能。也就是说,如果函数path的第二个参数是函数include,该路由为路由分发;如果函数path的第二个参数是项目应用views.py的视图函数或视图类,该路由为网站的路由地址。
5、路由变量规则
路由detail在路由地址里设置了路由变量id,通过动态改变路由变量id的数值就能生成相应的商品详细介绍页面,Django的路由变量分为字符类型、整型、slug和uuid,最为常用的是字符串型和整型。各个类型说明如下:
- 字符类型:匹配任何非空字符串,但不含斜杠。如果没有指定类型,就默认使用该类型。
- 整型:匹配0和正整数。
- slug:可理解为注释、后缀或附属等概念,常作为路由的解释型字符。可匹配任何ASCII字符以及连接符和下划线,能使路由更加清晰易懂。比如网页的标题是”13岁的孩子“,其路由地址可以设置为”13-sui-de-hai-zi“。
- uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用”-“并且所有字母必须小写,例如075194d3-6885-417e-a8a8-6c913e272f00。
在路由中,如果使用函数path定义路由,那么路由变量则使用变量符号”<>“定义。在括号里以冒号划分两部分,冒号前面代表的是变量的数据类型,冒号后面代表的是变量名,变量名可自行命名,如果没有设置变量的数据类型,就默认为字符类型。比如路由变量
除了在路由地址设置变量外,Django还支持在路由地址外设置变量(路由的可选变量),比如在路由detail的路由添加可选变量user,如下所示:
from django.urls import path
from .views import *
urlpatterns = [
path('.html', commodityView, {'user':'admin'}, name='commodity'),
path('/detail/<int:id>.html', detailView, name='detail')
]
从上述的代码可以看出来,可选变量的设置规则如下:
- 可选变量只能以字典表示。
- 设置的可选变量只能在视图函数中读取和使用。
- 字典的一个键值对代表一个可选变量,键值对的键代表变量名,键值对的值代表变量值。
- 变量值没有数据格式限制,可以为某个实例对象、字符串或列表(元组)等。
- 可选变量必须在视图函数(函数类)和参数name之间。
二、数据模型搭建与使用
1、数据模型的定义
1.1 数据模型即MTV当中的M(模型),模型简单来说就是通过Django内置的ORM方法编写去转换执行MySQL代码,建立MySQL数据表。模型都是一个一个的类方法,通过ORM方法将Python代码映射为MySQL代码。下面是部分常用的模型字段:
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,参数max_length表示最大字符个数,对应mysql中的varchar |
TextField | 大文本字段,一般大段文本(超过4000个字符)才使用。 |
IntegerField | 整数,长度为11位。 |
DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数,常用于表示分数和价格 Decimal(max_digits=7, decimal_places=2) ==> 99999.99~ 0.00 |
FloatField | 浮点数 |
DateField | 日期 参数auto_now表示每次保存对象时,自动设置该字段为当前时间。 参数auto_now_add表示当对象第一次被创建时自动设置当前。 参数auto_now_add和auto_now是相互排斥的,一起使用会发生错误。 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段,django在文件字段中内置了文件上传保存类, django可以通过模型的字段存储自动保存上传文件, 但是, 在数据库中本质上保存的仅仅是文件在项目中的存储路径!! |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
对模型字段约束条件(部分):
选项 | 说明 |
---|---|
null | 如果为True,表示允许为空,默认值是False。相当于python的None |
blank | 如果为True,则该字段允许为空白,默认值是False。 相当于python的空字符串,“” |
db_column | 字段的名称,如果未指定,则使用属性的名称。 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False。 相当于SQL语句中的key |
default | 默认值,当不填写数据时,使用该选项的值作为数据的默认值。 |
primary_key | 如果为True,则该字段会成为模型的主键,默认值是False,一般不用设置,系统默认设置。 |
unique | 如果为True,则该字段在表中必须有唯一值,默认值是False。相当于SQL语句中的unique |
max_length | 默认为None,设置字段的最大长度。 |
choices | 默认为空列表,设置字段的可选值。 |
1.2 模型建立完成之后需要在后面重写函数______str______(),这是直接设置模型的返回值,打印模型类会直接输出______str______()的返回值。方便mysql外键指向该模型调取返回值。一般返回值都是返回实例对象设置的主键(即self.id),同时需要注意的是返回值一般是字符类型,需要用到内置函数str() 转换,代码参考如下:
def __str__(self):
return str(self.id)
1.3 还需要重写Meta类,表示模型的属性,他是Model模型的子类,解释如下:
- 每个模型类(Model)下都有一个子类 Meta,这个子类就是定义元数据的地方。
- Meta 类封装了一些数据库的信息,称之为 Model 的元数据。
- Django 会将 Meta 中的元数据选项定义附加到 Model 中。
- 常见的元数据定义有 db_table(数据表名称)、abstract(抽象类) 、ordering(字段排序) 等,
- Meta 作为内部类,它定义的元数据可以让admin 管理后台对人类更加友好,数据的可读性更高。
Meta 定义的元数据相当于 Model 的配置信息,即不属于 Model 的字段,但是可以用来标识字段一些属性。一共有19个属性,举例基本常用的几种:
-
verbose_name:verbose_name的意思很简单,就是给你的模型类起一个更可读的名字一般定义为中文(在admin后台非常方便管理),我们:verbose_name="学校"。
-
verbose_name_plural:这个选项是指定,模型的复数形式是什么,比如:
verbose_name_plural="学校"
如果不指定Django会自动在模型名称后加一个’s’。
-
db_table:属性值为字符串,设置模型所对应的数据表名称。
-
app_lable:属性值为字符串,将模型设置为指定的项目应用,比如将当前App下的Model模型定义在其他App里。
-
ordering:属性值为列表,将模型数据以某个字段进行排序。
综上所述,模型字段、函数_______str______和Meta选项是模型定义的基本要素,模型字段的类型、_______str______和Meta视实际开发需求而定。
2、数据迁移创建数据表
2.1 数据迁移就是将模型里面定义的模型生成相应的数据表,首次在项目当中定义模型的时候,项目所配置的数据库里面并没有创建任何数据表,想要通过模型映射在MySQL当中创建数据表,需要将App的模型编写完成之后,通过终端的指令进行数据表的映射创建:
python manage.py makemigrations
输入指令后会在模型的每个App下migrations下面自动生成一个0001_initial.py文件。
2.2 0001_initial.py文件将models.py定义的模型生成数据表的脚本代码,该文件的脚本代码可被migrate指令执行,migrate指令会根据脚本代码的内容在数据库里创建相应的数据表:
python manage.py migrate # 第一次配置好数据库,命令会创建依赖数据表,第二次则将0001_initial.py模型映射到数据库。
2.3 如果在实际开发当中需要新增功能、优化现有功能等。只需要在App里面定义编写模型类,再次执行makemigrations和migrate指令即可。第二次执行makemigrations的时候会再次创建一个新文件0002_initial.py。每次执行的migrate都会记录在数据表django_migrations当中。字段的增删改只需在已有的模型中重新定义即可,然后执行上面两个命令。
2.4 migrate指令可以执行某个py文件,如果只想执行某个App应用的模型的话,只需要输入下面的指令中间用空格隔开即可:
python manage.py migrate 想执行的应用名 0001_initial
也可以使用Django内置的sqlmigrate指令查看原生SQL语句:
python manage.py migrate sqlmigrate 想查看的应用名 0001_initial
除此之外,Django还提供了许多数据迁移指令,此处暂时不在重复讲述。
3、数据的导入与导出
3.1 实际开发过程中,我们经常要对数据库的数据进行导入和导出操作,比如网站重构以及数据分析。可以使用Navicat软件的导出功能。除了使用可视化工具实现数据的导入和导出之外。Django还为我们提供了操作指令(loaddata和dumpdata)来实现数据的导入导出操作:
python manage.py dumpdata > data.json
dumpdata指令末端使用了符号'>'(注意两边的空格)和文件名data.json,这是将项目所有的数据都存放在data.json文件中,data.json文件存放在根目录之下,如果只想导出某个App的模型数据,则在dumpdata后面跟上App的名称即可,loaddata指令则是将数据导入进数据库,不需要使用'>'符号。
4、使用QuerySet操作数据
4.1 Django对数据库的数据进行增删改操作是借助内置的ORM框架提供的API方法实现的,简单说就是ORM框架的所有数据操作API是在QuerySet类里面定义的,然后由开发者自定义的模型对象调用QuerySet类。使用命令进入shell模式或者使用python控制台:
python manage.py shell
在Shell模式下,想要对指定数据表增加数据,则可以输入以下代码实现:
from 'App名'.model import '模型类名'
t = '模型类名()'
t.'表列名' = '新增的数据'
t.'表后一列名' = '新增的数据'
t.save() # 保存
# 数据新增后,查看新增数据的主键id
t.id
上述代码首先对模型类进行实例化,在对实例对象的属性进行赋值,从而实现MySQL数据表的新增数据操作。
4.2 除了上述方法外,数据新增还有以下3种常见方法,代码如下:
# 方法一
# 使用create方法实现数据新增
t = '模型类名'.objects.create('表列名'=‘新增的数据’, '表列名'='新增的数据')
# 新增数据后,获取新增数据的主键id
t.id
# 方法二
# 同样使用create方法,但数据以字典格式表示
d = dict('列名'='新增的数据', '列名'='新增的数据')
t = Types.objects.create(**d) # *(表示元组传输),**(表示字典传输)
# 新增数据后,获取新增数据的主键id
t.id
# 方法三
# 在实例化时直接设置属性值
t = '模型类名'.objects.create(firsts='新增的数据', seconds='童话故事')
# 保存
t.sava()
# 获取新增的主键id
t.id
4.3 一般在执行数据新增的时候,为了保证数据的有效性,我们需要对数据进行去重判断,确保数据不会重复新增。通过查询判断存在再进行新增数据与否太过于麻烦,Django提供了get_or_create方法,使用如下:
d = dict('列名'='新增数据', '列名'='新增数据')
t = Types.objects.get_or_create(**d)
# 新增数据后,获取新增数据的主键id
t[0].id
注:只要有一个添加的列数据与数据库表中列不一样就会执行新增操作,如果模型的每个字段只要和数据库表中某一行完全相等就不会新增数据。
除了get_or_create方法外,Django还定义了update_or_create方法,这是判断当前数据在数据表中是否存在,如果存在,则进行更新操作,否则在数据表里新增数据,使用说明如下:
# 第一次是新增数据
d = dict(firsts='儿童早教', seconds='儿童玩具')
t = Types.objects.update_or_create(**d)
t
# 第二次是修改数据
t = Types.objects.update_or_create(**d,defaults={'firsts':'教育资料'})
update_or_create是根据字典d的内容查找数据表的数据,如果能找到相匹配的数据,就执行数据修改,修改内容以字典格式传递给参数defaults即可;如果在数据表当中找不到匹配的数据,就将字典d的数据新增到数据表里。
如果要对某个数据执行数据批量新增操作,可以使用bulk_create方法来实现,只需将数据对象以列表或元组的形式传入bulk_create方法即可:
t1 = Types(firsts='儿童用品',seconds='湿纸巾')
t2 = Types(firsts='儿童用品',seconds='纸尿裤')
ojb_list = [t1, t2]
Types.objects.bulk_create(ojb_list)
4.4 更新数据的步骤与数据新增的步骤大致相同,唯一的区别在于数据对象来自数据表,因此需要执行一次数据查询,查询结果以对象的形式表示,并将对象的属性就行赋值处理,代码如下:
t = Types.objects.get(id=1)
t.firsts = '儿童用品'
t.save()
上述的代码获取数据表commodity_types里主键id等于1的数据对象t,然后修改数据对象t的firsts属性,从而完成数据修改操作。
除此之外,我们还可以使用update方法实现数据更新,使用方法如下:
# 批量更新一条或多条数据,查询方法使用filter
# filter以列表格式进行返回,查询结果可能是一条或多条数据
Types.objects.filter(id=1).update(seconds='男装')
# 更新数据以字典格式表示
d = dict(seconds='童鞋')
Types.objects.filter(id=1).update(**d)
# 不使用查询方法,默认对全表的数据进行更新
Types.objects.update(firsts='母婴用品')
# 使用内置的F方法实现数据的自增或自减
# F方法还可以在annotate或filter方法里使用
from django.db.model import F
t = Types.objects.filter(id=1)
# 将id字段的数据自增加10,自增或自减的字段必须为数字类型
t.update(id=F('id')+10)
在Django2.2或者以上版本新增了数据批量更新方法bulk_update,它的使用与批量更新方法bulk_create相似,使用说明明如下:
# 新增两行数据
t1 = Types.objects.create(firsts='奶粉辅食', seconds='纸尿片')
t2 = Types.objects.create(firsts='儿童用品', seconds='进口奶粉')
# 修改字段firsts和seconds的数据
t1.firsts = '儿童用品'
t2.seconds = '婴儿车'
# 批量修改字段firsts和seconds的数据
Types.objects.bulk_update([t1,t2],fields=['firsts', 'seconds'])
4.5 Django中删除数据有3种方式:删除数据表的全部数据、删除一行数据和删除多行数据,实际方式如下:
# 删除数据表中的全部数据
Types.objects.all().delete()
# 删除一条id为1的数据
Types.objects.get(id=1).delete()
# 删除多条数据
Types.objects.filter(firsts='儿童用品').delete()
注:如果删除数据的过程中,数据设有外键字段,就会同时删除外键关联的数据。
4.6 在项目下的shell模式下通过ORM框架提供的API方法实现数据查询(部分):
from index.model import import *
# 全表查询
# SQL:Select * from index_vocation; 数据以列表返回
v = Vocation.objects.all()
# 查询第一条数据,序列从0开始
# values_list方法,数据以列表返回,列表以字典表示
v = Vocation.objects.values_list('job')[:3]
v
<QuerySet [('软件工程师',),('文员',),('网站设计',)]>
# 使用get方法查询数据
# SQL:Select * from index_vocation where id=2
v = Vocation.objects.get(id==2)
v.job
4.7 Django在查询数据时,大多数查询都能使用ORM提供的API方法,但对于一些复杂的查询可能难以使用ORM的API实现,因此Django引入了原生SQL语句的执行方法。
- extra:结果集修改器,一种提供额外查询参数的机制。
- raw:执行原始SQL并返回模型实例对象。
- execute:直接执行自定义的SQL
4.7.1 extra适合用于ORM难以实现的查询条件,将查询条件使用原生SQL语法实现,此方法需要依靠模型对象,在某种情况下可以防止SQL注入。extra一共定义了6个参数,参数说明如下:
- select:添加新的查询字段,即新增并定义模型之外的字段。
- where:设置查询条件。
- params:如果where设置了字符串格式化%s,那么该参数为where提供数值。
- tables:连接其他数据表,实现多表查询。
- order_by:设置数据的排序方式。
- select_params:如果select设置字符串格式化%s,那么该参数为select提供数值。
# 查询字段job等于‘网站设计’的数据
# params为where的%s提供数值
Vocation.objects.extra(where=['job=%s'],params=['网站设计'])
<QuerySet [<Vocation:3>]>
4.7.2 下一步分析raw的语法,它和extra所实现的功能是相同的,只能实现数据查询操作,并且也要依靠模型对象,但从使用角度来说,raw更为直观易懂。参数如下:
- raw_query:SQL语句。
- params:如果raw_query设置字符串格式化%s,那么该参数为raw_query提供数值。
- translations:为查询的字段设置别名。
- using:数据库对象,即Django所连接的数据库。
上述参数只有raw_query为必选参数,其他参数可以根据需求自行选择。通过下面的代码案例实现数据查询:
v = Vocation.objects.raw('select * from index_vocation')
v[0]
<Vocation:1>
4.7.3 最后分析execute的语法,它执行SQL语句无需经过Django的ORM框架。我们知道Django连接数据库需要借助第三方模块实现连接过程,如MySQL的mysqlclient模块和SQLite的sqlite3模块等,这些模块连接数据库之后,可以通过游标的方式执行SQL语句,而execute就是使用这种方式执行SQL语句,使用方法如下:
from django.db import connection
cursor=connection.cursor()
# 执行SQL语句
cursor.execute('select * from index_vocation')
# 读取第一行数据
cursor.fetchone()
# 读取所有数据
# cursor.fetchall()
execute能够执行所有的SQL语句,但很容易收到SQL注入攻击,一般情况下不建议使用这种方法实现数据操作。尽管如此,它能补全ORM框架所缺失的功能,如执行数据库的村塾过程。
标签:模型,py,Django,urls,path,设计,数据,id,路由 From: https://www.cnblogs.com/cloud07/p/17726849.html