ORM 字段和参数
一、ORM字段
1、常用字段
AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
IntegerField
一个整数类型,范围在 -2147483648 to 2147483647。
CharField
字符类型,必须提供max_length参数, max_length表示字符长度。
DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例
FileField
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数: upload_to = "" 上传文件的保存路径(服务器路径)
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
2、实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | AutoField(Field) - int 自增列,必须填入参数 primary_key = True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key = True 注:当model中如果没有自增列,则自动会创建一个列名为 id 的列 from django.db import models class UserInfo(models.Model): # 自动创建一个列名为id的且为自增的整数列 username = models.CharField(max_length = 32 ) class Group(models.Model): # 自定义自增列 nid = models.AutoField(primary_key = True ) name = models.CharField(max_length = 32 ) SmallIntegerField(IntegerField): - 小整数 - 32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) - 2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) - 9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型参数 null:布尔值,指定该字段是否允许为空。默认为 False 。 blank:布尔值,指定该字段是否允许在表单中为空。默认为 False 。 db_index:布尔值,指定是否在数据库中为该字段创建索引。默认为 False 。 default:默认值,当没有提供字段值时使用的默认值。 editable:布尔值,指定字段是否可以在Admin中编辑。默认为 True 。 help_text:字段的帮助文本,通常在表单中显示。 verbose_name:字段的人类可读名称,通常在表单和Admin中显示。 validators:指定一组验证器,用于验证字段的值。 unique:布尔值,指定字段的值是否必须在整个表中唯一。默认为 False 。 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 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" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match = None , 正则匹配 recursive = False , 递归下面的文件夹 allow_files = True , 允许文件 allow_folders = False , 允许文件夹 ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field = None , 上传图片的高度保存的数据库字段名(字符串) height_field = None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期 + 时间格式 YYYY - MM - DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY - MM - DD TimeField(DateTimeCheckMixin, Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10 进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型 |
二、ORM字段参数
1、ORM字段参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | null 数据库中字段是否可以为空 db_column 数据库中字段的列名 db_tablespace default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices = [( 0 , '何穗' ),( 1 , '大表姐' ),],default = 1 ) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{ 'null' : "不能为空." , 'invalid' : '格式错误' } validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length = 32 , error_messages = { 'c1' : '优先错信息1' , 'c2' : '优先错信息2' , 'c3' : '优先错信息3' , }, validators = [ RegexValidator(regex = 'root_\d+' , message = '错误了' , code = 'c1' ), RegexValidator(regex = 'root_112233\d+' , message = '又错误了' , code = 'c2' ), EmailValidator(message = '又错误了' , code = 'c3' ), ] ) |
2、 重点)
作用
类似于一些字段:性别、学历、客户来源、是否上学、是否结婚等字段,能够被列举完。
存入数据库中是数字或者字母等,读取出来是汉字(字符串)。
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(max_length=64) # 增加一个性别字段:不要这样存字符串类型的,存数字, 1 2 3 男 gender_choices = ( (1, '男'), (2, '女'), (3, '未知'), ) '''该字段所存储的范围大小还是取决于字段类型的大小范围''' gender = models.SmallIntegerField(choices=gender_choices) # 1 2 3 """我们想实现的效果是:存的时候是数字,读出来是对应的文本内容""" # 定义一个分数的字段:A:优秀 B:良好 C:及格 D:不及格 score_choices = ( ('A', '优秀'), ('B', '良好'), ('C', '及格'), ('D', '不及格'), ) # 字段类型如何选择:就选择跟('A', '优秀')第一个参数错存得类型一致就行 score = models.CharField(max_length=64, choices=score_choices, default='A') |
读取数据
obj.get_字段名_display()
1 2 | instance = models.Userinfo.objects.get(pk = 1 ) print (instance.get_gender_display()) # 获取人类可读标签 |
实际案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | # choices它是ORM中常用字段中的参数 作用: 类似于一些字段:性别、学历、客户来源、是否上学、是否结婚等字段 # 针对于一些字段它的情况能够被列举完,像这样的字段,我们在表中存储的时候一般使用choices参数 案例 class Customer(models.Model): """ 客户表 """ qq = models.CharField(verbose_name = 'qq' , max_length = 64 , unique = True , help_text = 'QQ号必须唯一' ) name = models.CharField(verbose_name = '学生姓名' , max_length = 16 ) gender_choices = (( 1 , '男' ), ( 2 , '女' )) gender = models.SmallIntegerField(verbose_name = '性别' , choices = gender_choices) education_choices = ( ( 1 , '重点大学' ), ( 2 , '普通本科' ), ( 3 , '独立院校' ), ( 4 , '民办本科' ), ( 5 , '大专' ), ( 6 , '民办专科' ), ( 7 , '高中' ), ( 8 , '其他' ) ) education = models.IntegerField(verbose_name = '学历' , choices = education_choices, blank = True , null = True , ) graduation_school = models.CharField(verbose_name = '毕业学校' , max_length = 64 , blank = True , null = True ) major = models.CharField(verbose_name = '所学专业' , max_length = 64 , blank = True , null = True ) experience_choices = [ ( 1 , '在校生' ), ( 2 , '应届毕业' ), ( 3 , '半年以内' ), ( 4 , '半年至一年' ), ( 5 , '一年至三年' ), ( 6 , '三年至五年' ), ( 7 , '五年以上' ), ] experience = models.IntegerField(verbose_name = '工作经验' , blank = True , null = True , choices = experience_choices) work_status_choices = [ ( 1 , '在职' ), ( 2 , '无业' ) ] work_status = models.IntegerField(verbose_name = "职业状态" , choices = work_status_choices, default = 1 , blank = True , null = True ) company = models.CharField(verbose_name = "目前就职公司" , max_length = 64 , blank = True , null = True ) salary = models.CharField(verbose_name = "当前薪资" , max_length = 64 , blank = True , null = True ) source_choices = [ ( 1 , "qq群" ), ( 2 , "内部转介绍" ), ( 3 , "官方网站" ), ( 4 , "百度推广" ), ( 5 , "360推广" ), ( 6 , "搜狗推广" ), ( 7 , "腾讯课堂" ), ( 8 , "广点通" ), ( 9 , "高校宣讲" ), ( 10 , "渠道代理" ), ( 11 , "51cto" ), ( 12 , "智汇推" ), ( 13 , "网盟" ), ( 14 , "DSP" ), ( 15 , "SEO" ), ( 16 , "其它" ), ] source = models.SmallIntegerField( '客户来源' , choices = source_choices, default = 1 ) referral_from = models.ForeignKey( 'self' , blank = True , null = True , verbose_name = "转介绍自学员" , help_text = "若此客户是转介绍自内部学员,请在此处选择内部学员姓名" , related_name = "internal_referral" ) course = models.ManyToManyField(verbose_name = "咨询课程" , to = "Course" ) status_choices = [ ( 1 , "已报名" ), ( 2 , "未报名" ) ] status = models.IntegerField( verbose_name = "状态" , choices = status_choices, default = 2 , help_text = u "选择客户此时的状态" ) consultant = models.ForeignKey(verbose_name = "课程顾问" , to = 'UserInfo' , related_name = 'consultanter' , limit_choices_to = { 'depart' : 1001 }) date = models.DateField(verbose_name = "咨询日期" , auto_now_add = True ) recv_date = models.DateField(verbose_name = "当前课程顾问的接单日期" , null = True ) last_consult_date = models.DateField(verbose_name = "最后跟进日期" , ) def __str__( self ): return self .name class ConsultRecord(models.Model): """ 客户跟进记录 """ customer = models.ForeignKey(verbose_name = "所咨询客户" , to = 'Customer' ) consultant = models.ForeignKey(verbose_name = "跟踪人" , to = 'UserInfo' , limit_choices_to = { 'depart' : 1001 }) date = models.DateField(verbose_name = "跟进日期" , auto_now_add = True ) note = models.TextField(verbose_name = "跟进内容..." ) def __str__( self ): return self .customer.name + ":" + self .consultant.name class Student(models.Model): """ 学生表(已报名) """ customer = models.OneToOneField(verbose_name = '客户信息' , to = 'Customer' ) class_list = models.ManyToManyField(verbose_name = "已报班级" , to = 'ClassList' , blank = True ) emergency_contract = models.CharField(max_length = 32 , blank = True , null = True , verbose_name = '紧急联系人' ) company = models.CharField(verbose_name = '公司' , max_length = 128 , blank = True , null = True ) location = models.CharField(max_length = 64 , verbose_name = '所在区域' , blank = True , null = True ) position = models.CharField(verbose_name = '岗位' , max_length = 64 , blank = True , null = True ) salary = models.IntegerField(verbose_name = '薪资' , blank = True , null = True ) welfare = models.CharField(verbose_name = '福利' , max_length = 256 , blank = True , null = True ) date = models.DateField(verbose_name = '入职时间' , help_text = '格式yyyy-mm-dd' , blank = True , null = True ) memo = models.CharField(verbose_name = '备注' , max_length = 256 , blank = True , null = True ) def __str__( self ): return self .customer.name class ClassStudyRecord(models.Model): """ 上课记录表 (班级记录) """ class_obj = models.ForeignKey(verbose_name = "班级" , to = "ClassList" ) day_num = models.IntegerField(verbose_name = "节次" , help_text = u "此处填写第几节课或第几天课程...,必须为数字" ) teacher = models.ForeignKey(verbose_name = "讲师" , to = 'UserInfo' , limit_choices_to = { 'depart' : 1002 }) date = models.DateField(verbose_name = "上课日期" , auto_now_add = True ) course_title = models.CharField(verbose_name = '本节课程标题' , max_length = 64 , blank = True , null = True ) course_memo = models.TextField(verbose_name = '本节课程内容概要' , blank = True , null = True ) has_homework = models.BooleanField(default = True , verbose_name = "本节有作业" ) homework_title = models.CharField(verbose_name = '本节作业标题' , max_length = 64 , blank = True , null = True ) homework_memo = models.TextField(verbose_name = '作业描述' , max_length = 500 , blank = True , null = True ) exam = models.TextField(verbose_name = '踩分点' , max_length = 300 , blank = True , null = True ) def __str__( self ): return "{0} day{1}" . format ( self .class_obj, self .day_num) class StudentStudyRecord(models.Model): ''' 学生学习记录 ''' classstudyrecord = models.ForeignKey(verbose_name = "第几天课程" , to = "ClassStudyRecord" ) student = models.ForeignKey(verbose_name = "学员" , to = 'Student' ) record_choices = (( 'checked' , "已签到" ), ( 'vacate' , "请假" ), ( 'late' , "迟到" ), ( 'noshow' , "缺勤" ), ( 'leave_early' , "早退" ), ) record = models.CharField( "上课纪录" , choices = record_choices, default = "checked" , max_length = 64 ) score_choices = (( 100 , 'A+' ), ( 90 , 'A' ), ( 85 , 'B+' ), ( 80 , 'B' ), ( 70 , 'B-' ), ( 60 , 'C+' ), ( 50 , 'C' ), ( 40 , 'C-' ), ( 0 , ' D' ), ( - 1 , 'N/A' ), ( - 100 , 'COPY' ), ( - 1000 , 'FAIL' ), ) score = models.IntegerField( "本节成绩" , choices = score_choices, default = - 1 ) homework_note = models.CharField(verbose_name = '作业评语' , max_length = 255 , blank = True , null = True ) note = models.CharField(verbose_name = "备注" , max_length = 255 , blank = True , null = True ) homework = models.FileField(verbose_name = '作业文件' , blank = True , null = True , default = None ) stu_memo = models.TextField(verbose_name = '学员备注' , blank = True , null = True ) date = models.DateTimeField(verbose_name = '提交作业日期' , auto_now_add = True ) def __str__( self ): return "{0}-{1}" . format ( self .classstudyrecord, self .student) |
三、关系字段
1、ForeignKey 一对多字段。
外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 ‘一对多’中’多’的一方。
ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。
参数:
to 设置要关联的表
to_field 设置要关联的表的字段
1 2 3 4 5 | class Student(models.Model): name = models.CharField(max_length = 32 ) theclass = models.ForeignKey(to = "Classes" , related_name = "students" ) models.Classes.objects.first().students. all () |
related_query_name 反向查询操作时,使用的连接前缀,用于替换表名。
models.DO_NOTHING 删除关联数据,引发错误IntegrityError
models.PROTECT 删除关联数据,引发错误ProtectedError
models.SET_NULL 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
db_constraint 是否在数据库中创建外键约束,默认为True。
2、OneToOneField 一对一字段
3、ManyToManyField 用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系
多对多关联关系的三种方式(酌情选择)
方式一:自己创建第三张表,分别通过外键关联书和作者(全手动)
推荐使用全手动的创建方式,可扩展性高
第三张表需要我们自己手动创建,不会在自动创建了
优势:扩展性非常好
劣势:不能使用四个方法 add set remove clear
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Book(models.Model): title = models.CharField(max_length = 32 , verbose_name = "书名" ) class Author(models.Model): name = models.CharField(max_length = 32 , verbose_name = "作者姓名" ) # 自己创建第三张表,分别通过外键关联书和作者 class Author2Book(models.Model): author = models.ForeignKey(to = "Author" ) book = models.ForeignKey(to = "Book" ) class Meta: unique_together = ( "author" , "book" ) |
方式二:通过ManyToManyField自动创建第三张表(全自动)
扩展性不好,可以使用四个方法 add set remove clear
1 2 3 4 5 6 7 | class Book(models.Model): title = models.CharField(max_length = 32 , verbose_name = "书名" ) # 通过ORM自带的ManyToManyField自动创建第三张表 class Author(models.Model): name = models.CharField(max_length = 32 , verbose_name = "作者姓名" ) books = models.ManyToManyField(to = "Book" , related_name = "authors" ) |
方式三:设置ManyTomanyField并指定自行创建的第三张表(半自动)
支持正反向查询的,但是不支持那四个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Book(models.Model): title = models.CharField(max_length=32, verbose_name="书名") # 自己创建第三张表,并通过ManyToManyField指定关联 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) # through_fields接受一个2元组('field1','field2'): # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。 class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book") class Meta: unique_together = ("author", "book") |
注:
Author
表定义了作者的属性,包括 name
作为作者的姓名。另外,使用 ManyToManyField
来创建与 Book
表之间的多对多关系。
through:
指定中间关联表的名称为 Author2Book
,
through_fields
:指定在中间关联表中用来关联 Author
和 Book
模型的外键字段。