Django之模型定义与ORM操作
Django型与ORM
Django模型(Model)是一个Python类,它定义了和数据库表格中的字段对应的属性和方法。
在Django ORM中,模型通过继承django.db.models.Model来创建,每个模型对应数据库中的一张表,而模型的属性则对应表格中的字段。
通过定义模型,开发人员可以使用Python代码操作数据库,而无需直接编写SQL语句。
搭建基础项目环境
创建项目
django-admin startproject demo
创建应用
python manager.py startapp user
在settings.py
配置文件中注册应用
INSTALLED_APPS = [
# 添加应用
'user.apps.UserConfig'
]
配置MySQL
Django对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。Django为这些数据库提供了统一的调用API。这里使用MySQL数据库
Django默认初始配置使用sqlite数据库。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
安装MySQL驱动
使用MySQL数据库首先需要安装驱动程序
pip install PyMySQL
配置DATABASES信息
修改DATABASES节点配置信息,主要是指定数据库引擎、主机地址、端口、用户名、密码、数据库名称等信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库用户密码
'NAME': 'demo' # 数据库名字
}
}
在MySQL中创建数据库
create database demo charset=utf8;
配置Django的ORM
配置Django的ORM以mysqldb的方式调用PyMySQL。只需要在Django的工程同名子目录的__init__.py
文件中进行配置
import pymysql
pymysql.install_as_MySQLdb()
模型类
定义模型类
模型类被定义在”应用/models.py”文件中。
类名:通常使用大写字母开头的单词表示数据表名,例如class User(models.Model)。
属性:每个属性都对应数据库表格中的一个字段,例如CharField、IntegerField等,还可以自定义字段类型。
方法:模型类可以定义很多方法,用于实现数据操作逻辑,例如增删改查等。
Meta类:Meta类是用于定义模型元信息的类,比如指定表格名称、排序方式、关联表格等。
from django.db import models
# Create your models here.
class UserInfo(models.Model):
GENDER_CHOICES = (
(0, '未知'),
(1, '男'),
(2, '女')
)
# 创建字段 = 字段类型 字段宽度 字段说明 字段默认值
name = models.CharField(max_length=5, verbose_name='姓名')
age = models.IntegerField(default=0, verbose_name='年龄')
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
create_date = models.DateField(verbose_name='创建日期', null=True)
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
# 模型类如果未指明表名,Django默认以小写app应用名_小写模型类名为数据库表名
class Meta:
db_table = 'user' # 指明数据库表名
verbose_name = '用户信息' # 在admin站点中显示的名称
# 定义每个数据对象的显示信息
def __str__(self):
return self.name
class Address(models.Model):
description = models.CharField(max_length=100, null=True, verbose_name='详细地址')
user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name='用户') # 外键 对应数据库字段user_id
class Meta:
db_table = 'address'
verbose_name = '地址信息'
def __str__(self):
return self.description
创建表结构
1.生成迁移文件,让 Django 知道模型有一些变更
python manage.py makemigrations
2.创建表结构,同步到数据库中
python manage.py migrate
字段类型
Django模型中的字段类型用来定义数据库表格中的数据类型。
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,参数max_length表示最大字符个数 |
TextField | 大文本字段,一般超过4000个字符时使用 |
IntegerField | 整数 |
DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 |
FloatField | 浮点数 |
DateField | 日期 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,默认为False 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,默认为False 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段 |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
可选项配置
在Django模型中,每个字段类型都可以设置一些可选项来控制其行为和属性。
选项 | 说明 |
---|---|
null | 如果为True,表示允许为空,默认值是False |
blank | 如果为True,则该字段允许为空白,默认值是False |
db_column | 字段的名称,如果未指定,则使用属性的名称 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False |
default | 默认 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False |
外键
Django中外键(ForeignKey)是模型之间关联的一种方式。它定义了一个指向另一个模型的关系,使用其他模型的主键作为外键。
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
常量 | 说明 |
---|---|
CASCADE | 级联 删除主表数据时连通一起删除外键表中数据 |
PROTECT | 保护 通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据 |
SET_NULL | 设置为NULL,仅在该字段null=True允许为null时可用 |
SET_DEFAULT | 设置为默认值,仅在该字段设置了默认值时可用 |
SET() | 设置为特定值或者调用特定方法 |
DO_NOTHING | 不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常 |
Address模型定义了一个外键字段,它指向 UserInfo模型。参数 on_delete=models.CASCADE 定义了当关联的 UserInfo 对象被删除时,与其相关联的 Address对象应该如何处理(删除与之关联的所有 Address对象)
class UserInfo(models.Model):
name = models.CharField(max_length=5, verbose_name='姓名')
class Address(models.Model):
description = models.CharField(max_length=100, null=True, verbose_name='详细地址')
user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, verbose_name='用户')
shell工具
Django的shell工具是一个交互式Python环境,用于执行Django应用程序中的各种操作。使用shell工具,我们可以在命令行中直接访问Django的模型和查询集API,并对它们进行测试、调试和探索。
启动shell工具非常简单,只需要在Django项目的根目录中运行以下命令即可:
python manage.py shell
(py3) D:\WorkSpace\Python\demo>python manage.py shell
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
进入shell环境,就可以使用Python交互式解释器来执行各种操作
# 导入Person模型
from myapp.models import UserInfo
# 创建一个新的人员记录
user = UserInfo(name='John', age=25)
user.save()
# 查询所有年龄小于30岁的人员
user = UserInfo.objects.filter(age__lt=30)
增、删、改
增加
save:通过创建模型类对象,执行对象的save()方法保存到数据库中
>>> from user.models import UserInfo
>>> user = UserInfo(name='Jack', age=20, gender=1, create_date='2023-01-09', is_delete=False)
>>> user.save()
>>> user
<UserInfo: Jack>
>>>
create:通过模型类.objects.create()保存
>>> from user.models import UserInfo
>>> UserInfo.objects.create(name='Jack', age=20, gender=1, create_date='2023-01-09', is_delete=False)
<UserInfo: Jack>
>>>
修改
save:修改模型类对象的属性,然后执行save()方法
>>> user = UserInfo.objects.get(id=1)
>>> user.name='小白'
>>> user.save()
>>> user
<UserInfo: 小白>
>>>
update:使用模型类.objects.filter().update(),会返回受影响的行数
>>> UserInfo.objects.filter(name='小白').update(name='Jack')
1
>>>
删除
模型类对象delete方法
>>> user = UserInfo.objects.get(id=1)
>>> user.delete()
(1, {'user.UserInfo': 1})
>>>
模型类.objects.filter().delete()
>>> UserInfo.objects.filter(name='Jack').delete()
(1, {'user.UserInfo': 1})
>>>
查询
基础条件查询
基本查询
get:查询单一结果,如果不存在会抛出模型类.DoesNotExist异常
>>> UserInfo.objects.get(id=1)
all:查询多个结果
>>> UserInfo.objects.all()
<QuerySet [<UserInfo: Jack>, <UserInfo: 小白>]>
>>>
count:查询结果数量
>>> UserInfo.objects.count()
2
>>>
过滤查询
过滤条件查询,提供三个方法,其用法基本一致
filter:查询符合条件的数据
exclude:查询不符合条件的数据
get:查询符合条件的返回模型类对象,符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误
UserInfo.objects.filter(name='Django')
UserInfo.objects.exclude(name='Django')
UserInfo.objects.get(name='Django')
比较运算符
等值查询
exact:判断是否相等
>>> UserInfo.objects.get(id=1)
<UserInfo: Jack>
>>> UserInfo.objects.get(id__exact=1)
<UserInfo: Jack>
>>>
模糊查询
contains:是否包含
startswith、endswith:以指定值开头或结尾
>>> UserInfo.objects.filter(name__contains='Ja')
<QuerySet [<UserInfo: Jack>, <UserInfo: Jack>]>
>>> UserInfo.objects.filter(name__startswith='Ja')
<QuerySet [<UserInfo: Jack>, <UserInfo: Jack>]>
>>>
注意:
1.属性名称和比较运算符间使用两个下划线分割,因此属性名不能包括多个下划线
2.以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith
空查询
isnull:是否为null
>>> UserInfo.objects.filter(name__isnull=True)
<QuerySet []>
范围查询
in:是否包含在范围内
查询ID为1或3的数据
>>> UserInfo.objects.filter(id__in=[1,3])
<QuerySet [<UserInfo: Jack>, <UserInfo: Jack>]>
比较查询
gt:大于 (greater then)
gte:大于等于 (greater then equal)
lt:小于 (less then)
lte:小于等于 (less then equal)
不等于:使用exclude()过滤器
>>> UserInfo.objects.filter(id__gt=4)
日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
>>> UserInfo.objects.filter(create_date__year=2023)
<QuerySet [<UserInfo: Jack>, <UserInfo: 小白>, <UserInfo: Jack>]>
>>> UserInfo.objects.filter(create_date__gt='2022-01-01')
<QuerySet [<UserInfo: Jack>, <UserInfo: 小白>, <UserInfo: Jack>]>
>>>
聚合函数
聚合函数是一种查询结果的汇总计算方法。聚合函数可以将多个查询结果合并为一个单一的结果。Django提供了多个内置聚合函数
Avg():返回给定字段的平均值
Count():返回匹配查询条件的结果数
Max():返回给定字段的最大值
Min():返回给定字段的最小值
Sum():返回给定字段的总和
使用aggregate()过滤器调用聚合函数
>>> from django.db.models import Sum
>>> UserInfo.objects.aggregate(Avg('age'))
使用count时一般不使用aggregate()过滤器,count函数返回值是一个数字
UserInfo.objects.count()
排序
使用order_by对结果进行排序
默认升序
>>> UserInfo.objects.all().order_by('id')
降序
按照降序排序,在字段前使用 -(减号)标识
>>> UserInfo.objects.all().order_by('-id')
基本关联查询
由一到多的访问语法:
一对应的模型类对象.多对应的模型类名小写_set
查询一个用户对应的多个地址信息
>>> from user.models import UserInfo
>>> user = UserInfo.objects.get(id=1)
>>> user.address_set.all()
<QuerySet [<Address: 某省某城市某区1>, <Address: 某省某城市某区2>]>
由多到一的访问语法:
多对应的模型类对象.多对应的模型类中的关系类属性名
查询一个地址对应的用户
>>> from user.models import Address
>>> address = Address.objects.get(id=1)
>>> address.user
<UserInfo: Jack1>
>>>
访问一端对应的模型类关联对象的id语法: 多对应的模型类对象.关联类属性_id
查询一个地址对应用户的id值
>>> address = Address.objects.get(id=1)
>>> address.user_id
4
关联过滤查询
由多模型类条件查询一模型类数据:
关联模型类名小写__属性名__条件运算符=值
查询用户信息,并且地址信息包含’四川省’
>>> user = UserInfo.objects.filter(address__description__contains='四川省')
>>> user
由一模型类条件查询多模型类数据:
一模型类关联属性名__一模型类属性名__条件运算符=值
查询Jack用户的所有地址信息
>>> address = Address.objects.filter(user__name='Jack')
>>> address
注意:如果没有"__运算符"部分,表示等于。
F对象
F对象可以在查询中对数据库字段进行操作,允许使用数据库本身的运算符来比较两个字段并对它们进行操作
导入F对象
from django.db.models import F
语法格式:
F(属性名)
查询id值大于等于age字段值
UserInfo.objects.filter(id__gt=F('age'))
更新查询中所有行中一个字段的值,使其等于另一个字段
UserInfo.objects.all().update(money=F('age'))
在F对象上使用算数运算
UserInfo.objects.filter(id__gt=F('age') / 2)
Q对象
Q对象是用于构造复杂查询的工具。它可以将多个条件组合成一个复杂的查询,并且可以与其他查询操作符一起使用。
导入Q对象
from django.db.models import Q
逻辑或
Q对象用于实现逻辑或的查询。
语法:
Q(属性名__运算符=值)
Q对象可以使用&、|连接
&:表示逻辑与
|:表示逻辑或
Q对象也可以使用~操作符,表示非not
>>> UserInfo.objects.filter(~Q(id=2))
查询id值大于5,或则id小于10
UserInfo.objects.filter(Q(id__gt=5)|Q(id__lt=10))
逻辑与
多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字
查询id值大于5,并且id小于10
>>> UserInfo.objects.filter(id__gt=5,id__lt=10)
>>> UserInfo.objects.filter(id__gt=5).filter(id__lt=3)
查询姓名是F或者姓名是Q的用户,且年龄在18岁以上
>>> UserInfo.objects.filter(Q(name='F') | Q(name='Q'), age__gte=18)
查询集QuerySet
概念
查询集(QuerySet)是一种表示数据库中一组数据的对象。它是从模型中检索出来的数据集合,并且可以进行过滤、排序、限制等操作。
查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果。从SQL的角度讲,查询集与select语句等价,过滤器像where、limit、order by子句。
当调用如下过滤器方法时,Django会返回查询集,而不是简单的列表:
all():返回所有数据
filter():返回满足条件的数据
exclude():返回满足条件之外的数据
order_by():对结果进行排序
判断一个查询集中是否有数据
exists():判断查询集中是否有数据,如果有则返回True,没有则返回False
查询集支持链式调用,对查询集可以再次调用过滤器进行过滤
>>> user = UserInfo.objects.filter(age__gt=15).order_by('create_date')
>>>> user.exists()
True
>>> user
<QuerySet [<UserInfo: Jack1>, <UserInfo: Jack2>, <UserInfo: Jack3>, <UserInfo: Jack4>]>
访问查询集
for user in users:
print(user.name, user.age)
获取前五个人的查询集
users = UserInfo.objects.all()[:5]
两大特性
1.惰性执行
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用
当执行如下语句时,并未进行数据库查询,只是创建了一个查询集
# 只创建查询集,并未进行数据库查询
>>> users = UserInfo.objects.all()
# 真正进行数据库查询
for user in users:
print(user.name)
2.缓存
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
情况1:如下两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。
>>> [user.id for user in UserInfo.objects.all()]
[1, 2, 3, 4]
>>> [user.id for user in UserInfo.objects.all()]
[1, 2, 3, 4]
情况2:经过存储后,可以重用查询集,第二次使用缓存中的数据。
>>> users =UserInfo.objects.all()
>>> [user.id for user in users]
[1, 2, 3, 4]
>>> [user.id for user in users]
[1, 2, 3, 4]
限制查询集
限制操作是非常常见的查询集操作之一,在Django中非常方便易用。无论是切片、跳过、获取第一个/最后一个对象还是计算结果数,都可以轻松地实现。这些操作通常是通过Python的切片语法来实现的。
可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。查询集进行切片后返回一个新的查询集,不会立即执行查询。
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()如果没有数据引发DoesNotExist异常。
获取第1、2项,限制为前2个人
>>> users = UserInfo.objects.all()[0:2]
>>> users
<QuerySet [<UserInfo: Jack1>, <UserInfo: Jack2>]>
使用first()和last()方法来获取查询集中的第一个和最后一个对象
与切片不同,first()和last()方法只返回一个结果,而不是返回整个查询集。
UserInfo.objects.order_by('age').first()
UserInfo.objects.order_by('age').last()
分页
在Django中,可以使用Paginator类来进行分页。
#查询数据
>>> users = UserInfo.objects.all().order_by("id")
#导入分页类
>>> from django.core.paginator import Paginator
#创建分页实例
>>> paginator=Paginator(users,2)
#获取指定页码的数据
>>> page_num = paginator.page(1)
#获取分页数据
>>> total_page=paginator.num_pages
>>>
>>> page_num
<Page 1 of 2>
>>> total_page
2
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136842.html