Django:必会ORM查
1.ORM常用字段
- 在models.py,创建表中字段
1.1AutoField
自增的整形字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django自动创建。一个model不能有两个AutoField字段。
from django.db import models class Person(models.Model): pid = models.AutoField(primary_key=True)
1.2 IntegerField
一个整数类型。数值的范围是 -2147483648 ~ 2147483647。
class Person(models.Model): age = models.IntegerField()
1.3 CharField
字符类型,必须提供max_length参数。max_length表示字符的长度。
class Person(models.Model): name = models.CharField(max_length=32)
1.4 DateField
日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例。
参数:
- auto_now:每次修改时修改为当前日期时间。
- auto_now_add:新创建对象时自动添加当前日期时间。
- 需要注意:default auto_now_add auto_now 之间是互斥的,只能填写一个
class Person(models.Model): birth = models.DateField(auto_now_add=True)
1.5 DatetimeField
日期时间字段,格式为YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime的实例。
class Person(models.Model): birth = models.DateTimeField(auto_now_add=True)
1.6 BooleanField
布尔值
class Person(models.Model): gender = models.BooleanField("性别",choices=((0,"男"),(1,"女")))
1.7 DecimalField
十进制小数
参数:
- max_digits 总长度
- decimal_places 小数位数
class Person(models.Model): money = models.DecimalField(max_digits =5,decimal_places=3)
1.8 TextField
- 文本类型
1.9 了解即可:
1.BigAutoField bigint自增列,必须填入参数 primary_key = True 2。SmallIntegerField(IntegerField) 小整数 -32768 ~ 32767 3.PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 正小整数 0 ~ 32767 4.IntegerField(Field) 整数列(有符号的) -2147483648 ~ 2147483647 5.PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 正整数 0 ~ 2147483647 6.BigIntegerField(IntegerField) 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 7.NullBooleanField(Field) 可以为空的布尔值 8.EmailField(CharField) 字符串类型,Django Admin以及ModelForm中提供验证机制 9.IPAddressField(Field) 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 10.GenericIPAddressField(Field) 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" 11.URLField(CharField) 字符串类型,Django Admin以及ModelForm中提供验证 URL 12.SlugField(CharField) 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) 13.CommaSeparatedIntegerField(CharField) 14.UUIDField(Field) 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 15.FilePathField(Field) 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 16.FileField(Field) 字符串,路径保存在数据库,文件上传到指定目录 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 17.ImageField(FileField) 字符串,路径保存在数据库,文件上传到指定目录 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) 18.TimeField(DateTimeCheckMixin, Field) 时间格式 HH:MM[:ss[.uuuuuu]] 19.DurationField(Field) 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 20.FloatField(Field) 浮点型 21.DecimalField(Field) 10进制小数 参数: max_digits,小数总长度 decimal_places,小数位长度 22.BinaryField(Field) 二进制类型
注意:当model中如果没有自增列,则自动回创建一个列名为id的列
2.自定义字段
- 在models.py自定义一个char字段类型
class MyCharField(models.Field): 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): return "char(%s)"%(self.max_length)
- 使用自定义字段:
class Person(models.Model): iphone = MyCharField(max_length=11)
3.Django 中超级用户的激活和表的注册
- 在Terminal 输入命令 python3 manage.py createsuperuser
表的注册:在admin.py文件输入
from django.contrib import admin from app01 import models admin.site.register(models.Person)
4.字段参数的设置
- 常用字段参数设置
null 数据库中字段是否可以为空 db_column 数据库中字段的列名 default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 index_together 联合索引 unique_together 联合唯一索引
null与blank
class Person(models.Model): iphone = MyCharField(max_length=11,null=True) #表示数据库可以为null,默认null为False #设置改变数据库属性必须执行数据库迁移命令如null,改变Django内form表单可以不用执行数据库命令,如blank # 一般blank和null同时出现。blank=True from表单填写时为可以为空
db_column
class Person(models.Model): name = models.CharField(max_length=32,db_column="username") #django字段显示name,在数据库中显示为username
default
class Person(models.Model): age = models.IntegerField(default=18) #需要注意:default auto_now_add auto_now 之间是互斥的,只能填写一个
verbose_name/db_table/verbose_name_plural
class Meta: db_table = "个人管理" verbose_name = "个人信息表" verbose_name_plural = "哈哈" #verbose_name也可以给字段设置admin显示的内容 age = models.IntegerField(default=18, verbose_name='年纪', editable=True)
verbose_name_plural:
verbose_name:
? db_table:
editable
#当给age设置editable为Fasle,则admin页面将不会显示age class Person(models.Model): age = models.IntegerField(default=18, verbose_name='年纪', editable=False)
help_text帮助提示信息
class Person(models.Model): age = models.IntegerField(default=18, verbose_name='年纪',help_text="不是农历岁数")
显示在admin:
choices
class Person(models.Model): gender = models.BooleanField("性别",choices=((0,"男"),(1,"女")))
显示效果:
class Meta常用参数
model = models.Student #对应的Model中的类 fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段 exclude = None #排除的字段 labels = None #提示信息 help_texts = None #帮助提示信息 widgets = None #自定义插件 error_message = None #自定义错误信息
5.Model Meta 参数设置
- 不经常用,如果有特殊需要可以使用
class Person(models.Model): ...... class Meta: db_table = "个人管理" verbose_name = "个人信息表" verbose_name_plural = "哈哈" #联合索引 index_together=[ ("name","age"), ] #联合唯一索引 unique_together = (("iphone","birth"),)
6.在交互模式下创建数据
- pycharm内置交互模式启动Django,可以执行代码。
增: obj = models.Person.objects.create(name="xjk",iphone="13589306703",gender=0) 删: obj.delete() 改: obj.update(name="xujunkai") 查: obj = models.Person.objects.filter(pk=5)
7.ORM查询必知(13条)
- 在项目目录下创建文件夹
- 再在文件夹下创建py文件
- 导入模块(先配置环境再django.setup())
#必须按照这个顺序,否则报错 import os import django os.environ.setdefault("DJANGO_SETTINGS_MODULE","mro_lianxi.settings")#mro_lianxi为项目名称 django.setup() from app01 import models
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
- 查询
#all() 获取所有的数据 --->QuerySet 对象列表 ret = models.Person.objects.all() print(ret) #get() 获取满足条件的一个数据 ---->对象(获取不到或者多个报错) ret = models.Person.objects.get(pk=1) print(ret) #filter() 获取满足条件所有数据 ---> QuerySet 对象列表 ret = models.Person.objects.filter(pk=1) print(ret) #exclude() 获取不满足条件的所有数据 ---> QuerySet 对象列表 ret = models.Person.objects.exclude(pk=1) print(ret) #values() 获取对象所有的字段和字段的值 QuerySet[{},{}] #values(字段) 获取对象指定的字段和字段值 QuerySet[{},{}] ret = models.Person.objects.values() print(ret) ret = models.Person.objects.values("pid","name") print(ret) # values_list() 拿到对象所有的字段值 QuerySet[(),()] ret = models.Person.objects.values() print(ret) # order_by 排序 '-'号代表降序 ----> QuerySet[(),()] ret = models.Person.objects.order_by("age","-pid")#按照age升序,pid降序 print(ret) #reverse 反向排序 只对已经排序的QuerySet进行反转 ret = models.Person.objects.all().order_by("pk").reverse() print(ret) #distinct 去重 完全相同才能去重... 拿到values 是一个QuerySet对象,里面装字典键age, 给age相同去重 ret = models.Person.objects.values("age").distinct() print(ret) #count 计数 ret = models.Person.objects.all().count() print(ret) #first 取第一个元素 没有元素 None ret = models.Person.objects.all().values().first() print(ret) #last 取最后一个元素 没有元素None ret = models.Person.objects.all().values().last() print(ret) # exists 查询数据是否存在 ret = models.Person.objects.filter(pk=10000).exists() print(ret)
注意:
class Meta: ordering = ("pk") #默认排序 此处有坑 #不要再Meta设置排序,这样会导致后面使用其他方法查表,查询无效 #如: distinct 去重 失效
- 小结:
1.返回QuerySet all() filter() exclude() values() values_list() order_by() reverse() distinct() 2.返回一个对象 get() first() last() 3.返回数字 count() 4.返回布尔值 exists()
8.单表查询之神奇的双下划线
#gt # 大于(greater than) #获取pk大于1。 ret = models.Person.objects.filter(pk__gt=1) print(ret) #lt #小于(less than) #获取pk小于3 ret = models.Person.objects.filter(pk__lt=3) print(ret) #gte #大于等于(greater than equal) #获取pk大于等于2 ret = models.Person.objects.filter(pk__gte=2) print(ret) #lte #小于等于(less than equal) #获取pk 小于等于3 ret = models.Person.objects.filter(pk__lte=3) print(ret) #range #范围 #获取pk 在2~4之间的对象 ret = models.Person.objects.filter(pk__range=[2,4]) print(ret) #in #成员判断 #获取pk 在[1,2,5,10]里的 ret = models.Person.objects.filter(pk__in=[1,2,5,10]) print(ret) #contains #获取name有a的对象 ret = models.Person.objects.filter(name__contains="a") print(ret) #icontains #获取name有a的,不区分大小写 ret = models.Person.objects.filter(name__icontains="a") print(ret) #startswith #获取name以a开头的 ret = models.Person.objects.filter(name__startswith='a') # 以什么开头 print(ret) #istartswith #获取name以a开头的,不区分大小写 ret = models.Person.objects.filter(name__istartswith='a') print(ret) #endswith #获取name以a结尾的对象 ret = models.Person.objects.filter(name__endswith='a') # 以什么结尾 print(ret) #iendswith #获取name 以a结尾的对象,不区分大小写 ret = models.Person.objects.filter(name__iendswith='a') print(ret) #year #获取birth里的year 为2019的对象 ret = models.Person.objects.filter(birth__year='2019') print(ret) #contains #获取birth年月日为2017-06-24的对象 #会有warning警告 ret = models.Person.objects.filter(birth__contains='2017-06-24') print(ret) #isnull #获取iphone 为是null的对象 ret = models.Person.objects.filter(iphone__isnull=True) print(ret)
9.外键的操作
- 首先创建2张外键关联表
- 代码:
#models.py class Publisher(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey(Publisher,on_delete=models.CASCADE) def __str__(self): return self.title
在orm_test下创建py文件,并导入模块
import os import django os.environ.setdefault("DJANGO_SETTINGS_MODULE","mro_lianxi.settings") django.setup() from app01 import models
基于对象的查询
#正向查找(Book有关联的外键,先查询有外键关联的) #通过查书的名字,从而查到出版社 book_obj = models.Book.objects.get(title="Go基础") print(book_obj.pub) #图灵出版社 #反向查询 (类名小写_set) #通过查询出版社--->来查询到出版的书 pub_obj = models.Publisher.objects.get(pk=2) print(pub_obj.book_set.all())
related_name使用
#models.py class Publisher(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey(Publisher,related_name='books',on_delete=models.CASCADE) def __str__(self): return self.title #当把Book的pub字段设置related_name='books',则反向查找方式更改为 pub_obj = models.Publisher.objects.get(pk=2) print(pub_obj.books.all())
基于字段的查询
#查询title为Go基础的对象 ret = models.Book.objects.filter(title="Go基础") print(ret) #查询图灵出版社出版的书 ret = models.Book.objects.filter(pub__name="图灵出版社") print(ret) #当related_name = "books" #反向查找: ret= models.Publisher.objects.filter(books__title='Go基础') print(ret) #当设置related_query_name="mybook" 和related_name = "books" ret= models.Publisher.objects.filter(mybook__title='Go基础') print(ret)
练习题:https://www.cnblogs.com/maple-shaw/articles/9414626.html