文章对应的B站视频:https://www.bilibili.com/video/BV1Tu41127Ca/
Django系列文章对应的目录:
Django ORM - 单表实例
阅读本节前你需要先阅读了 Django 模型 进行基础配置及了解常见问题的解决方案。
接下来我们重新创建一个项目 app01(如果之前已创建过,忽略以下操作):
D:\temp-test\djangodemo>django-admin startproject app01
接下来在 app01\app01\settings.py 中找到 INSTALLED_APPS 这一项,如下:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01', # 添加此项
)
修改 settings.py 文件中找到 DATABASES 配置项,将其信息修改为:
DATABASES = {
'default':
{
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'mydb', # 数据库名称
'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1
'PORT': 3306, # 端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库密码
}
}
接下来,告诉 Django 使用 pymysql 模块连接 mysql 数据库:
实例
# 在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置 (D:\temp-test\djangodemo\app01\app01\__init__.py)
import pymysql
pymysql.install_as_MySQLdb()
创建模型
在项目中新建 models.py 并添加以下类:
app01/models.py (D:\temp-test\djangodemo\app01\app01\models.py)
from django.db import models
class Book(models.Model):
id = models.AutoField(primary_key=True) # id 会自动创建,可以手动写入
title = models.CharField(max_length=32) # 书籍名称
price = models.DecimalField(max_digits=5, decimal_places=2) # 书籍价格
publish = models.CharField(max_length=32) # 出版社名称
pub_date = models.DateField() # 出版时间
然后在命令行执行以下命令:
$ python manage.py migrate # 创建表结构
$ python manage.py makemigrations app01 # 让 Django 知道我们在我们的模型有一些变更
$ python manage.py migrate app01 # 创建表结构
D:\temp-test\djangodemo\app01>
D:\temp-test\djangodemo\app01>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
No migrations to apply.
D:\temp-test\djangodemo\app01>python manage.py makemigrations app01
Migrations for 'app01':
app01\migrations\0001_initial.py
- Create model Book
D:\temp-test\djangodemo\app01>python manage.py migrate app01
Operations to perform:
Apply all migrations: app01
Running migrations:
Applying app01.0001_initial... OK
这时数据库 就会创建一个 app01_book 的表。
接下来我们在app01 项目里添加 views.py 文件,app01 项目目录结构:
数据库添加
规则配置:
app01/urls.py: 文件代码:
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('add_book/', views.add_book),
]
方式一:模型类实例化对象
需从 app 目录引入 models.py 文件:
from app 目录 import models
并且实例化对象后要执行 对象.save() 才能在数据库中新增成功。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
book = models.Book(title="入门教程",price=300,publish="入门出版社",pub_date="2008-8-8")
book.save()
return HttpResponse("<p>数据添加成功!</p>")
python manage.py runserver 8003
D:\temp-test\djangodemo\app01>python manage.py runserver 8003
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
January 30, 2022 - 11:17:17
Django version 4.0.1, using settings 'app01.settings'
Starting development server at http://127.0.0.1:8003/
Quit the server with CTRL-BREAK.
http://127.0.0.1:8003/add_book/
方式二:通过 ORM 提供的 objects 提供的方法 create 来实现(推荐)
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.create(title="Django入门系列",price=50,publish="Django出版社",pub_date="2022-01-30")
print(books, type(books)) # Book object (18)
return HttpResponse("<p>数据添加成功!</p>")
http://127.0.0.1:8003/add_book/
查找
all() 方法
来查询所有内容。
返回的是 QuerySet 类型数据,类似于 list,里面放的是一个个模型类的对象,可用索引下标取出模型类的对象。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.all()
print(books,type(books)) # QuerySet类型,类似于list,访问 url 时数据显示在命令行窗口中。
return HttpResponse("<p>查找成功!</p>")
http://127.0.0.1:8003/add_book/
CMD 输出:
System check identified no issues (0 silenced).
January 30, 2022 - 12:22:45
Django version 4.0.1, using settings 'app01.settings'
Starting development server at http://127.0.0.1:8003/
Quit the server with CTRL-BREAK.
<QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> <class 'django.db.models.query.QuerySet'>
[30/Jan/2022 12:23:35] "GET /add_book/ HTTP/1.1" 200 22
views.py
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.all()
for i in books:
print(i.title, i.price, i.publish)
#print(books,type(books)) # QuerySet类型,类似于list,访问 url 时数据显示在命令行窗口中。
return HttpResponse("<p>查找成功!</p>")
CMD输出:
Starting development server at http://127.0.0.1:8003/
Quit the server with CTRL-BREAK.
入门教程 300.00 入门出版社
Django入门系列 50.00 Django出版社
[30/Jan/2022 12:27:35] "GET /add_book/ HTTP/1.1" 200 22
filter() 方法
用于查询符合条件的数据。
返回的是 QuerySet 类型数据,类似于 list,里面放的是满足条件的模型类的对象,可用索引下标取出模型类的对象。
pk=1 的意思是主键 primary key=1,相当于 id=1。
因为 id 在 pycharm 里有特殊含义,是看内存地址的内置函数 id(),因此用 pk。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.filter(pk=2)
print(books)
print("//////////////////////////////////////")
books = models.Book.objects.filter(publish='Django出版社')
print(books, type(books)) # QuerySet类型,类似于list。
return HttpResponse("<p>查找成功!</p>")
CMD输出:
Starting development server at http://127.0.0.1:8003/
Quit the server with CTRL-BREAK.
<QuerySet [<Book: Book object (2)>]>
//////////////////////////////////////
<QuerySet [<Book: Book object (2)>]> <class 'django.db.models.query.QuerySet'>
[30/Jan/2022 12:30:37] "GET /add_book/ HTTP/1.1" 200 22
exclude() 方法
用于查询不符合条件的数据。
返回的是 QuerySet 类型数据,类似于 list,里面放的是不满足条件的模型类的对象,可用索引下标取出模型类的对象。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.exclude(pk=1)
print(books)
print("//////////////////////////////////////")
books = models.Book.objects.exclude(publish='出版社')
print(books, type(books)) # QuerySet类型,类似于list。
return HttpResponse("<p>查找成功!</p>")
Starting development server at http://127.0.0.1:8003/
Quit the server with CTRL-BREAK.
<QuerySet [<Book: Book object (2)>]>
//////////////////////////////////////
<QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> <class 'django.db.models.query.QuerySet'>
[30/Jan/2022 12:32:41] "GET /add_book/ HTTP/1.1" 200 22
get() 方法
用于查询符合条件的返回模型类的对象符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.get(pk=1)
books = models.Book.objects.get(pk=18) # 报错,没有符合条件的对象
books = models.Book.objects.get(price=50) # 报错,符合条件的对象超过一个
print(books, type(books)) # 模型类的对象
return HttpResponse("<p>查找成功!</p>")
order_by() 方法
用于对查询结果进行排序。
返回的是 QuerySet类型数据,类似于list,里面放的是排序后的模型类的对象,可用索引下标取出模型类的对象。
注意:
- a、参数的字段名要加引号。
- b、降序为在字段前面加个负号 -。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.order_by("price") # 查询所有,按照价格升序排列
books = models.Book.objects.order_by("-price") # 查询所有,按照价格降序排列
return HttpResponse("<p>查找成功!</p>")
reverse() 方法
用于对查询结果进行反转。
返回的是 QuerySe t类型数据,类似于 list,里面放的是反转后的模型类的对象,可用索引下标取出模型类的对象。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
# 按照价格升序排列:降序再反转
books = models.Book.objects.order_by("-price").reverse()
return HttpResponse("<p>查找成功!</p>")
count() 方法
用于查询数据的数量返回的数据是整数。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.count() # 查询所有数据的数量
books = models.Book.objects.filter(price=50).count() # 查询符合条件数据的数量
return HttpResponse("<p>查找成功!</p>")
first() 方法
返回第一条数据返回的数据是模型类的对象也可以用索引下标 [0]。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.first() # 返回所有数据的第一条数据
return HttpResponse("<p>查找成功!</p>")
last() 方法
返回最后一条数据返回的数据是模型类的对象不能用索引下标 [-1],ORM 没有逆序索引。
app01/views.py: 文件代码:
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.last() # 返回所有数据的最后一条数据
return HttpResponse("<p>查找成功!</p>")
exists() 方法
用于判断查询的结果 QuerySet 列表里是否有数据。
返回的数据类型是布尔,有为 true,没有为 false。
注意:判断的数据类型只能为 QuerySet 类型数据,不能为整型和模型类的对象。
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.exists()
# 报错,判断的数据类型只能为QuerySet类型数据,不能为整型
books = models.Book.objects.count().exists()
# 报错,判断的数据类型只能为QuerySet类型数据,不能为模型类对象
books = models.Book.objects.first().exists()
return HttpResponse("<p>查找成功!</p>")
values() 方法
用于查询部分字段的数据。
返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个可迭代的字典序列,字典里的键是字段,值是数据。
注意:
参数的字段名要加引号
想要字段名和数据用 values
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
# 查询所有的id字段和price字段的数据
books = models.Book.objects.values("pk","price")
print(books[0]["price"],type(books)) # 得到的是第一条记录的price字段的数据
return HttpResponse("<p>查找成功!</p>")
values_list() 方法
用于查询部分字段的数据。
返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个个元组,元组里放的是查询字段对应的数据。
注意:
参数的字段名要加引号
只想要数据用 values_list
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
# 查询所有的price字段和publish字段的数据
books = models.Book.objects.values_list("price","publish")
print(books)
print(books[0][0],type(books)) # 得到的是第一条记录的price字段的数据
return HttpResponse("<p>查找成功!</p>")
distinct() 方法
用于对数据进行去重。
返回的是 QuerySet 类型数据。
注意:
- 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在。
- distinct() 一般是联合 values 或者 values_list 使用。
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
# 查询一共有多少个出版社
books = models.Book.objects.values_list("publish").distinct() # 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在。
books = models.Book.objects.distinct()
return HttpResponse("<p>查找成功!</p>")
filter() 方法
基于双下划线的模糊查询(exclude 同理)。
注意:filter 中运算符号只能使用等于号 = ,不能使用大于号 > ,小于号 < ,等等其他符号。
__in 用于读取区间,= 号后面为列表 。
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
# 查询价格为200或者300的数据
books = models.Book.objects.filter(price__in=[200,300])
return HttpResponse("<p>查找成功!</p>")
__gt 大于号 ,= 号后面为数字。
# 查询价格大于200的数据
books = models.Book.objects.filter(price__gt=200)
__gte 大于等于,= 号后面为数字。
# 查询价格大于等于200的数据
books = models.Book.objects.filter(price__gte=200)
__lt 小于,=号后面为数字。
# 查询价格小于300的数据
books=models.Book.objects.filter(price__lt=300)
__lte 小于等于,= 号后面为数字。
# 查询价格小于等于300的数据
books=models.Book.objects.filter(price__lte=300)
__range 在 ... 之间,左闭右闭区间,= 号后面为两个元素的列表。
books=models.Book.objects.filter(price__range=[200,300])
__contains 包含,= 号后面为字符串。
books=models.Book.objects.filter(title__contains="菜")
__icontains 不区分大小写的包含,= 号后面为字符串。
books=models.Book.objects.filter(title__icontains="python") # 不区分大小写
__startswith 以指定字符开头,= 号后面为字符串。
books=models.Book.objects.filter(title__startswith="菜")
__endswith 以指定字符结尾,= 号后面为字符串。
books=models.Book.objects.filter(title__endswith="教程")
__year 是 DateField 数据类型的年份,= 号后面为数字。
books=models.Book.objects.filter(pub_date__year=2008)
__month 是DateField 数据类型的月份,= 号后面为数字。
books=models.Book.objects.filter(pub_date__month=10)
__day 是DateField 数据类型的天数,= 号后面为数字。
books=models.Book.objects.filter(pub_date__day=01)
删除
方式一:使用模型类的 对象.delete()。
返回值:元组,第一个元素为受影响的行数。
books=models.Book.objects.filter(pk=1).first().delete()
方式二:使用 QuerySet 类型数据.delete()(推荐)
返回值:元组,第一个元素为受影响的行数。
books=models.Book.objects.filter(pk__in=[1,2]).delete()
注意:
- a. Django 删除数据时,会模仿 SQL约束 ON DELETE CASCADE 的行为,也就是删除一个对象时也会删除与它相关联的外键对象。
- b. delete() 方法是 QuerySet 数据类型的方法,但并不适用于 Manager 本身。也就是想要删除所有数据,不能不写 all。
books=models.Book.objects.delete() # 报错
books=models.Book.objects.all().delete() # 删除成功
修改
方式一:
模型类的对象.属性 = 更改的属性值
模型类的对象.save()
返回值:编辑的模型类的对象。
books = models.Book.objects.filter(pk=7).first()
books.price = 400
books.save()
方式二:QuerySet 类型数据.update(字段名=更改的数据)(推荐)
返回值:整数,受影响的行数
实例
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
books = models.Book.objects.filter(pk__in=[7,8]).update(price=888)
return HttpResponse(books)
REF
https://www.runoob.com/django/django-orm-1.html