django-orm
Posted wenshu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django-orm相关的知识,希望对你有一定的参考价值。
-
Django-orm定义
实现数据库的sql操作转换为接口的形式,定义的类对应mysql的表,属性对应的是数据库的字段,实例对应数据库的一条记录
-
Django-orm 基础字段
2.1 所有字段都有的参数
db_column= "AA" 设置字段名称
primary_key=True 设置主键
verbose_name = "B" 设置字段别名
unique = True #设置唯一值属性
null = True blank=True # 默认情况下所有字段都不能为空,null字段设置允许为空(数据库层面),blank=True指的是前端表单提交允许为空
db_index = True 给字段建立索引
help_text = "AA" 在表单中显示说明信息
editable = False 字段不能编辑,默认字段都是可以编辑的
default = "AA" 设置默认值
2.2 个别字段的参数
max_length = 100 CharField必须要设置最大长度
auto_now = True DateField使用,默认填充当前时间,指的是数据更新的时间
auto_now_add = True DateField使用,指的是数据插入的时间
max_digits =4 DecimalField,设置所有的数字个数
decimal_places = 2 DecimalField,设置小数位的数字个数
2.3 关系型字段的参数
OneToOneField
ForeignKey
ManyToManyField
related_name = "one" 反向查询,可以通过父表查询到子表的信息
on_delete =models.CASCADE 当表关联的外键被删除时候对应的操作,一共由6种
models.CASCADE # 删除级联,删除A表的数据,B表关联的数据一起被删除
2.4 基础字段参数
class Test(models.Model):
# 自增长字段,默认是int型
Auto = models.AutoField()
BigAuto = models.BigAutoField()
# 二进制数据
Binary = models.BinaryField()
# 布尔型
Boolean = models.BooleanField() # 不允许为空的布尔
NullBoolean = models.NullBooleanField()
# 整型
PositiveSmallInteger = models.PositiveSmallIntegerField() # 5个字节
SmallInteger = models.SmallIntegerField()
PositiveInteger = models.PositiveIntegerField()
Integer = models.IntegerField() # 11个字节
BigInteger = models.BigIntegerField()
# 字符串类型
Char = models.CharField() # 需要指定默认长度
Text = models.TextField() # 不需要指定长度,可以存大量文字
# 时间日期类型
Date = models.DateField() # 年月日
DateTime = models.DateTimeField() # 年月日 时分秒
Duration = models.DurationField() # int型的时间
# 浮点型
float = models.FloatField()
Decimal = models.DecimalField()
# 其它字段
Email = models.EmailField() # 邮箱
Image = models.ImageField()
File = models.FileField() # 文件
FilePath = models.FilePathField() # 文件路径
URL = models.URLField()
UUID = models.UUIDField()
GenericIPAddress = models.GenericIPAddressField() # ipv4 ipv6
class Test_A(models.Model):
# 关系型字段
onetoone = models.OneToOneField(Test,on_delete=models.CASCADE)
class Test_B(models.Model):
foreign = models.ForeignKey(Test_A)
class Test_C(models.Model):
manytomany = models.ManyToManyField(Test_B)
2.5 自关联
class AdddressInfo(models.Model):
"省市县地址信息"
address= models.CharField(max_length=200,verbose_name="地址")
pid = models.ForeignKey("AdddressInfo",null=True,blank=True,verbose_name="自关联",on_delete=models.CASCADE)
# 可以取到这个表自己的字段
2.6 元数据
class Meta: # 每个模型类都由一个子类Meta,定义元数据的地方,封装了一些数据表的信息
db_table="address" # 定义表的名称
ordering = "pid" # 按照pid字段来排序
verbose_name = "地址" # 设置别名
verbose_name_plural = verbose_name # 设置别名复数
abstract = True # 设置这个类为基类,仅供其它类继承,自身不生成表
2.7 取choice里面的显示值
type = models.CharField(choices=((0,‘test00‘),(1,‘test11‘),(2,‘test22‘)))
def __str__(self):
return self.address+self.get_type_display()
# 在数据库实际存储的是 0,1,2,但是页面展示的是test00 test11 test22,但是在数据库取值的时候可以通过 get+字段名+display() 的方式取值(django orm方法)
2.8 表结构
所以可以科学的删除数据表(了解了makemigrations migrate 的用处)
makemigrations: 通过models生成一个表执行文件到migrations文件夹下面
migrate:执行这个表执行文件(生成或者修改表记录)
2.9 数据的创建
bulk_create : 批量导入
update_or_create: 创建或者更新
get_or_create: 取值或者创建
当导入的表结构含有外键属性的时候: 可以直接使用
teacher = Teacher.object.get(A="A") teacher 是course表的字段,Teacher是course的关联表。
-
QuerySet api
3.1返回新的QuerySet api
1. all() get() order_by() exclude() reverse() distinct()
exclude() 排除指定条件的结果集
2. values() values_list() 获取字典或者元组形式的QuerySet
例如:
Teacher.Objects.values("nickname","111")
>>> [{"nickname":"别名","111":"123"},{},{}] 字典格式的QuerySet
>>> [("nickname":"别名","111":"123"),(),()] 元组格式的QuerySet
3. 反向查询通过父表查询子表
子表查询父表的数据:
当导入的表结构含有外键属性的时候: 可以直接使用
teacher = Teacher.object.get(A="A") teacher 是course表的字段,Teacher是course的关联表。
父表查询子表的数据:
Teacher.objects.get(A="A").course_set.all() Teacher是父表,course是子表,格式是(子表名_set)
3.2 不返回QuerySet Api
get() 查询单个对象
get_or_create() 查询或者创建
Author.objects.get_or_create(nickname="hello",default={"name":"123"})
备注:主键或者唯一键写在外面,如果有,获取返回的值;没有,使用default里面的值创建
create() 创建
bulk_create() 批量创建 传的值是列表
update_or_create() 创建或更新,用法同get_or_create()
update() 更新
delete() 删除
exist() 判断是否存在
count() 计数
3.3 F对象和Q对象
F对象的使用:操作字段的数据
Q对象: 结合AND OR NOT | ~ & 实现复杂的查询
& 与
| 或
NOT 取反
-
其它
4.1新建一个对象的方法有以下几种:
# 方法 1
Author.objects.create(name="WeizhongTu", email="tuweizhong@163.com")
# 方法 2
twz = Author(name="WeizhongTu", email="tuweizhong@163.com")
twz.save()
# 方法 3--------------------常用
twz = Author()
twz.name="WeizhongTu"
twz.email="tuweizhong@163.com"
twz.save()
# 方法 4,首先尝试获取,不存在就创建,可以防止重复
Author.objects.get_or_create(nickname="hello",default={"name":"123"})
备注:主键或者唯一键写在外面,如果有,获取返回的值;没有,使用default里面的值创建
# 返回值(object, True/False)
备注:前三种方法返回的都是对应的 queryset object,最后一种方法返回的是一个元组,(object, True/False),创建时返回 True, 已经存在时返回 False
4.2 获取对象有以下方法
Person.objects.all() # 返回QuerySet结果集
Person.objects.all()[:10] 切片操作,获取10个人,不支持负索引,切片可以节约内存
Person.objects.get(name=name) ## 名称为 WeizhongTu 的一条,多条会报错
A:get是用来获取一个对象的,get返回的是结果,如果获取到多个会报错,通常传主键或者唯一键作为查询条件
B:filter获取满足条件的一些结果,filter返回的是结果集(QuerySet,类似于list,可以使用for循环来取值,支持切片))
Person.objects.filter(name="abc",address = "北京") Person.objects.filter(name__exact="abc") 名称严格等于 "abc" 的人
A:逗号代表与的关系,
B:mes= Person.objects.filter(name="abc",address = "北京") #返回queryset对象,获取不到返回None
print(mes.name) #返回的是多条记录的对象[object1,object2,objevt3],对象有字段的方法 mes.name
C: 字段__+关键字(对字段进行特殊orm操作:)
例如: name__exact="abc" 刚好等于
name__gte = 大于
name__in= 在列表范围内
D:Person.objects.all().order_by("字段名") 以。。进行排序(默认升序排列)
Person.objects.all().order_by("-字段名") 降序排列
E:查看原生的SQL
str(Person.objects.all().order_by.query)
Person.objects.filter(name__iexact="abc") # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
Person.objects.filter(name__contains="abc") # 名称中包含 "abc"的人
Person.objects.filter(name__icontains="abc") #名称中包含 "abc",且abc不区分大小写,模拟sql中like语句
Person.objects.filter(name__regex="^abc") # 正则表达式查询
Person.objects.filter(name__iregex="^abc") # 正则表达式不区分大小写
filter是找出满足条件的,当然也有排除符合某条件的
Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person对象
Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名称含有abc, 但是排除年龄是23岁的
4.3删除符合条件的结果
和上面类似,得到满足条件的结果,然后 delete 就可以(危险操作,正式场合操作务必谨慎),比如
Person.objects.filter(name__contains="abc").delete() # 删除 名称中包含 "abc"的人
如果写成
people = Person.objects.filter(name__contains="abc")
people.delete()
效果也是一样的,Django实际只执行一条 SQL 语句。
4.4更新某个内容
(1) 批量更新,适用于 .all() .filter() .exclude() 等后面 (危险操作,正式场合操作务必谨慎)
1
2
|
Person.objects.filter(name__contains="abc").update(name=‘xxx‘) # 名称中包含 "abc"的人 都改成 xxx
Person.objects.all().delete() # 删除所有 Person 记录
|
(2) 单个 object 更新,适合于 .get(), get_or_create(), update_or_create() 等得到的 obj,和新建很类似。
1
2
3
4
|
twz = Author.objects.get(name="WeizhongTu")
twz.name="WeizhongTu"
twz.email="tuweizhong@163.com"
twz.save() # 最后不要忘了保存!!!
|
QuerySet 是可迭代的,比如:
es = Entry.objects.all()
for e in es:
print(e.headline)
Entry.objects.all() 或者 es 就是 QuerySet 是查询所有的 Entry 条目。
注意事项:
(1). 如果只是检查 Entry 中是否有对象,应该用 Entry.objects.all().exists()
(2). QuerySet 支持切片 Entry.objects.all()[:10] 取出10条,可以节省内存
(3). 用 len(es) 可以得到Entry的数量,但是推荐用 Entry.objects.count() (等价于 es.count())来查询数量,后者用的是SQL:SELECT COUNT(*)
(4). list(es) 可以强行将 QuerySet 变成 列表
以上是关于django-orm的主要内容,如果未能解决你的问题,请参考以下文章