第十一章 ORM基础操作
1.orm的字段和参数
1.1 常用字段
1.AutoFiled 自增
-
自增的整型字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django会自动创建主键
-
一个model不能有两个AutoFiled字段。
2.intergerfield 整数
-
-
范围:-2147483648 ~ 2147483647
3.CharFiled 字符串
-
必须提供 max_length参数,表示字符的最大长度
4. DateField
-
日期类型,格式为YYYY-MM-DD,相当于python中的datetime.date的实例
-
参数:
-
auto_now:修改时,时间自动改变
-
auto_now_add:创建时,自动添加当前时间(使用orm操作时有效)
-
与default两两互斥,不能同时使用
-
5.DateTimeField
-
日期时间字段,格式为YYYY-MM-DD HH:MM[:ss [.uuuuuu]] [TZ],相当于Python中的datetime.datetime的实例
-
python console —> Django console(测试使用)
-
# models.py birth = models.DateTimeField(auto_now_add=True) auto_now_add=True # 新增数据的时候会自动保存当前的时间,修改的时候不会变 auto_now=True # 新增、修改数据的时候会自动保存当前的时间 auto_now_add和auto_now不能同时设置,是互斥的
#view.py from app01 import models obj = models.Person.objects.create(name='henry', age=19)
-
修改时,只有相应字段会变化,auto_now会自动更新到当前时间
-
models中修改参数,在数据库中会生效
6. DecimalField(Field)
-
10进制小数
-
参数:
-
max_digits,小数总长度
-
decimal_places,小数位长度
-
7. FloatField()
-
浮点型
8. 其他
-
BoolenField(Field)
-
存储bool值,可以使用在性别等(只有两种情况)
-
-
TextField(Field)
-
null=True
-
-
EmailField(CharField)
-
存储到数据库之前,会校验格式
-
-
BinaryField(Field)
-
二进制类型
-
9. 自定义字段
-
重写init方法,一般都是通过*args和**kwargs传参
-
在框架中一般使用super(类,self),在加上自己的操作
-
定义db_type(self, connection)
# models.py class MyCharField(models.Field): """自定义的char类型的字段类""" def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) # 指定生成数据库字段的类型 def db_type(self, connection): """限定生成数据库表的字段类型为char,长度为max_length指定的值""" return 'char(%s)' % self.max_length
- 使用自定义字段
# models.py class Test(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=20) # 使用自定义的char类型的字段,MyCharField为自定义的char cname = MyCharField(max_length=20)
1.2 字段参数(11)
# 默认null=False,表示数据存入时可以为空 cname = models.CharField(max_length=25, null=True)
2. blank=True
-
-
创建admin账户
# django,admin 是否为空,创建时需要 enable admin 否则自己注册admin和添加url路径 console: >>> python manage.py createsuperuser >>> 用户名、emial、密码(8位,不能是纯数字)
- 注册model类
# app的 admin.py 中 from django.contrib import admin from . import models # 注册,类 admin.site.register(models.Person) # form表单,数据库最终存储空的字符串 cname = models.CharField(max_length=25, null=True, blank=True)
- 多列显示
# admin.py from django.contrib import admin from rabc import models class PermissionConf(admin.ModelAdmin): # 展示多列 list_display = ['id', 'url', 'title'] # 可编辑的 list_editable = ['url', 'title'] admin.site.register(models.Permission, PermissionConf)
-
form表单填写时可以为空,可以不执行数据库迁移命令
3. db_column='new_name'
-
指定数据库的字段名
-
db_column:列名
# 数据库的字段为username,表已经存在不修改字段名使用 name = CharField(max_length=25, db_column='username')
4. default='xxx'
-
设置默认值
-
添加新的字段时使用
gender = models.BooleanFiled(default=0)
5. primary_key=True
pid = models.AutoField(primary_key=True) The primary key field is read-only. If you change the value of the primary
key on an existing object and then save it, a new object will be created alongside
the old one. # 主键字段只能读取,不能修改,一旦修改,django会默认创建一个新的对象
-
给当前字段添加索引
age = models.IntegerField(db_index=True)
-
唯一约束
name = models.CharField(max_length=32, unique=True)
-
verbose_name
-
'提示'(改变amdin中前端显示)
name = models.CharField(max_length=32, verbose_name='姓名')
- editable=False
# null 和 blank 一般成对出现 addr = models.CharField(max_length=50, null=True, blank=True, verbose_name='地址', editable=True)
- help_text='不要写乳名'
name = models.CharField(max_length=32, verbose_name='姓名', help_text='xxx')
# select框,(数据库存储的数据,'前端显示') # choices参数需要使用 tuple 嵌套tuple 进行设定 class Peroson(models.Model): gender = models.BooleanField('性别',choices=((0,'female'),(1, 'male'))) class Test(models.Model): gender_list = (('0', 'female'), (1, 'male'),) gender = models.CharField(max_length=1, choices=gender_list) >>> from app01 import models >>> p = models.Test() >>> p.gender='0' >>> p.get_gender_display() 'female'
-
**表的参数
class Person(models.Model): pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField(default=18) class Meta: # 设置默认排序 ordering = ('pk',...) # 此处有坑,请谨慎驾驶 # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "person" # admin中显示的表名称,此时在主页面上会显示‘个人信息s’ verbose_name = '个人信息' # verbose_name_plural和 verbose_name 一般成对使用 verbose_name_plural = '所有用户信息' # 联合索引 index_together = [ ("name", "age"), ] # 应为两个存在的字段 # 联合唯一索引 unique_together = (("name", "age"),) # 应为两个存在的字段
3.1 orm_test
-
测试文件准备
import os os.environ.setdefault('DJANGO_SETTINGS_MODULE','orm_practice.settings') import django django.setup() # models导入必须在setup之后 from app01 import models
3.2 orm操作
-
返回对像列表
-
all/filter/exclude/values/values_list/order_by/reverse/disctinct
-
-
返回对象(3)
-
get/first/last
-
-
返回bool值(1)
-
exists
-
-
返回数字(1)
-
count
-
# orm操作 # 获取所有对象 1.obj = models.Person.objects.all() # 获取一个对象 2.obj = models.Person.objects.get(pk=1) # 获取满足条件的所有数据,QuerySet类型,查询不到为[ ] 3.obj = models.Person.objects.filter(age=18) # 获取 不 满足条件的所有数据 4.obj = models.Person.objects.exclude(age=18) # 获取所有字段和字段值,QuerySet类型(里面嵌套dict), 参数不写默认所有 # 按照指定的顺序获取 5.obj = models.Person.objects.values(字段名1, 字段名2...) # 获取所有 字段值 ,QuerySet类型(里面嵌套tuple), 参数不写默认所有 # 按照指定的顺序获取 6.obj = models.Person.objects.values_list(字段名1, 字段名2...) # 默认生序排序, -pk 表示降序排序,可以指定多个字段 7.obj = models.Person.objects.all().order_by('age', '-pk') # 反转, 前提是排好序的 8.obj = models.Person.objects.all().order_by('pk').reverse() # 去重,内容完全相同可以去重,受默认排序影响,不支持字段去重 9.obj = models.Person.objects.values('age').distinct() # 计数 10.obj = models.Person.objects.all().count() # first/last, 没有则是None, 取第一/最后一个元素,没有则为None 11.obj = models.Person.objects.all/filter().first() 12.obj = models.Person.objects.values().first() # exists,判断查询的数据是否存在,必须是QuerySet 13.obj = models.Person.objects.get(pk=1).exists()
4. 双下线方法(8)
-
在单表中,提供范围查找的方法
-
字段__双下方法
4.1 __gt/lt= 大于/小于
# gt greater than, 大于2 obj = models.Person.objects.filter(pk__gt=2) # lt, 小于2 obj = models.Person.objects.filter(pk__lt=2)
# gte/lte, 大于等于/小于等于 obj = models.Person.objects.filter(pk__gte=2)
# 组合,或者range,闭区间 obj = models.Person.objects.filter(pk__gte=2,pk__lt=3) obj = models.Person.objects.filter(pk__range=[2,3])
# in,条件判断,符合list中条件的 obj = models.Person.objects.filter(pk__in=[1, 3])
4.5 __contains='h'
# contains='xxx',区分大小写, __icontains='h',忽略大小写 obj = models.Person.objects.filter(name__contains='h')
4.6 __startswith/endswith
-
__istartswith/iendswith
# startswith='h', 和 __istartswith='' / endswith obj = models.Person.objects.filter(name__startswith='h')
# 筛选年份,不支持月和日 obj = models.Person.objects.filter(birth__year='2019') obj = models.Person.objects.filter(birth__contains='2019-06')
4.8 __isnull=True
obj = models.Person.objects.filter(birth__isnull=True)
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=32) class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey('Publisher', related_name='books' ,on_delete=models.CASCADE)
5.1 基于对象的查询
# Book --> Publisher:正向查询 book_obj = models.Book.objects.get(pk=1).pub
- 反向查询
# 反向查询 pub_obj = models.Publisher.objects.get(pk=1) # 关联的 类名小写_set,set集合,pub_obj必须唯一 pub_obj.book_set # 关系管理对象 pub_obj.book_set.all() # 关联的所有书籍 # 指定 realated_name进行反向查询名称 pub_obj.books.all() # 关联的所有书籍
5.2 基于字段查询
-
relate_query_name
-
relate_query_name默认值为related_name
-
__字段名
# 表示跨表查找出版社name book_obj = models.Book.objects.filter(pub__name='人民出版社')
- 反向查询
# 指定related_name=books,查询指定书的出版社 pub_obj = models.Publisher.objects.filter(books__title='python之旅') # 不指定related_name,查询指定书的出版社,使用类名小写 pub_obj = models.Publisher.objects.filter(book__title='python之旅') # 指定related_name=books,related_query_name='xxx',查询指定书的出版社 pub_obj = models.Publisher.objects.filter(xxx__title='python之旅')