Django框架Day3------之Models
一、Django models字段类型清单:
AutoField:一个自动递增的整型字段,添加记录时它会自动增长。你通常不需要直接使用这个字段;如果你不指定主键的话,系统会自动添加一个主键字段到你的model。(参阅自动主键字段)
BooleanField:布尔字段,管理工具里会自动将其描述为checkbox。
CharField:字符串字段,单行输入,用于较短的字符串,如要保存大量文本, 使用 TextField,CharField有一个必填参数:
CharField.max_length:字符的最大长度,django会根据这个参数在数据库层和校验层限制该字段所允许的最大字符数。
TextField:一个容量很大的文本字段, admin 管理界面用 <textarea>多行编辑框表示该字段数据。
CommaSeparatedIntegerField:用于存放逗号分隔的整数值。类似 CharField,必须maxlength 参数。
DateField:日期字段,admin 用一个文本框 <input type=”text”> 来表示该字段数据(附带一个 JavaScript 日历和一个”Today”快捷按键。有下列额外的可选参数:
auto_now:当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 “last-modified” 时间戳;
auto_now_add:当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间。
DateTimeField:类似 DateField 支持同样的附加选项。
EmailField:一个带有检查 Email 合法性的 CharField,不接受 maxlength 参数。
FileField:一个文件上传字段。 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径。 这个路径必须包含 strftime formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don’t fill up the given directory)。在一个 model 中使用 FileField 或 ImageField 需要以下步骤:在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件。 (出于性能考虑,这些文件并不保存到数据库。) 定义 MEDIA_URL 作为该目录的公共 URL。 要确保该目录对 WEB 服务器用户帐号是可写的。在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪个子目录保存上传文件。你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT)。 出于习惯你一定很想使用 Django 提供的 get_<fieldname>_url 函数。举例来说,如果你的 ImageField 叫作 mug_shot, 你就可以在模板中以 {{ object。get_mug_shot_url }} 这样的方式得到图像的绝对路径。
FilePathField:选择指定目录按限制规则选择文件,有三个参数可选, 其中”path”必需的,这三个参数可以同时使用, 参数描述:
path:必需参数,一个目录的绝对文件系统路径。 FilePathField 据此得到可选项目。 Example: “/home/images”;
match:可选参数, 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名。 注意这个正则表达式只会应用到 base filename 而不是路径全名。 Example: “foo。*\。txt^”, 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif;
recursive:可选参数, 是否包括 path 下全部子目录,True 或 False,默认值为 False。
match 仅应用于 base filename, 而不是路径全名。 如:FilePathField(path=”/home/images”, match=”foo.*”, recursive=True)…会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
FloatField:浮点型字段。 必须提供两个参数,参数描述:
max_digits:总位数(不包括小数点和符号)
decimal_places:小数位数。如:要保存最大值为 999 (小数点后保存2位),你要这样定义字段:models.FloatField(…,max_digits=5, decimal_places=2),要保存最大值一百万(小数点后保存10位)的话,你要这样定义:models.FloatField(…,max_digits=19, decimal_places=10)
ImageField:类似 FileField, 不过要校验上传对象是否是一个合法图片。它有两个可选参数:height_field 和 width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存。 该字段要求 Python Imaging 库。
IntegerField:用于保存一个整数。
IPAddressField:一个字符串形式的 IP 地址, (如 “202.1241.30″)。
NullBooleanField:类似 BooleanField, 不过允许 NULL 作为其中一个选项。 推荐使用这个字段而不要用 BooleanField 加 null=True 选项。 admin 用一个选择框 <select> (三个可选择的值: “Unknown”, “Yes” 和 “No” ) 来表示这种字段数据。
PhoneNumberField:一个带有合法美国风格电话号码校验的 CharField(格式:XXX-XXX-XXXX)。
PositiveIntegerField:类似 IntegerField, 但取值范围为非负整数(这个字段应该是允许0值的…可以理解为无符号整数)
PositiveSmallIntegerField:正小整型字段,类似 PositiveIntegerField, 取值范围较小(数据库相关)SlugField“Slug” 是一个报纸术语。 slug 是某个东西的小小标记(短签), 只包含字母、数字、下划线和连字符。它们通常用于URLs。 若你使用 Django 开发版本,你可以指定 maxlength。 若 maxlength 未指定, Django 会使用默认长度: 50,它接受一个额外的参数:
prepopulate_from: 来源于slug的自动预置列表
SlugField:是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.它们通常用于URLs。
SmallIntegerField:类似 IntegerField, 不过只允许某个取值范围内的整数。(依赖数据库)
TimeField:时间字段,类似于 DateField 和 DateTimeField。
URLField:用于保存 URL。 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在(即URL是否被有效装入且没有返回404响应)。
USStateField:美国州名缩写,由两个字母组成(天朝人民无视)。
XMLField:XML字符字段,校验值是否为合法XML的 TextField,必须提供参数:
schema_path:校验文本的 RelaxNG schema 的文件系统路径。
附:Field 选项
-
null :缺省设置为false.通常不将其用于字符型字段上,比如CharField,TextField上.字符型字段如果没有值会返回空字符串。
-
blank:该字段是否可以为空。如果为假,则必须有值
-
choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。如SEX_CHOICES= ((‘F’,'Female’),(‘M’,'Male’),)
-
core:db_column,db_index 如果为真将为此字段创建索引
-
default:设定缺省值
-
editable:如果为假,admin模式下将不能改写。缺省为真
-
help_text:admin模式下帮助文档
-
primary_key:设置主键,如果没有设置django创建表时会自动加上:
id = meta.AutoField('ID', primary_key=True) primary_key=True implies blank=False, null=False and unique=True. Only one primary key is allowed on an object.
- radio_admin:用于admin模式下将select转换为radio显示。只用于ForeignKey或者设置了choices
- unique:数据唯一
- unique_for_date:日期唯一,如下例中系统将不允许title和pub_date两个都相同的数据重复出现
- title = meta.CharField(maxlength=30,unique_for_date=’pub_date’)
- unique_for_month / unique_for_year:用法同上
- validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误
附代码 参考:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # -*- coding:utf-8 -*- 2 from django.db import models 3 4 # Create your models here. 5 from django.core.exceptions import ValidationError 6 from django.db import models 7 from django.contrib.auth.models import User 8 9 10 course_type_choices = ( 11 ('online',u'网络班'), 12 ('offline_weekend',u'面授班(周末)',), 13 ('offline_fulltime',u'面授班(脱产)',), 14 ) 15 16 class School(models.Model): 17 name = models.CharField(max_length=128,unique=True) 18 city = models.CharField(max_length=64) 19 addr = models.CharField(max_length=128) 20 21 def __unicode__(self): 22 return self.name 23 24 25 class UserProfile(models.Model): 26 user = models.OneToOneField(User) 27 name = models.CharField(max_length=64) 28 school = models.ForeignKey('School') 29 30 def __unicode__(self): 31 return self.name 32 33 34 class Customer(models.Model): 35 qq = models.CharField(max_length=64, unique=True) 36 name = models.CharField(max_length=32, blank=True, null=True) 37 phone = models.BigIntegerField(blank=True, null=True) 38 course = models.ForeignKey('Course') 39 40 course_type = models.CharField(max_length=64,choices=course_type_choices,default='online') 41 consult_memo = models.TextField() 42 source_type_choices = (('qq',u'qq群'), 43 ('referral',u'内部转介绍'), 44 ('51cto',u'51cto'), 45 ('agent',u'招生代理'), 46 ('others',u'其他'), 47 ) 48 source_type = models.CharField(max_length=64,choices=source_type_choices,default='qq') 49 referral_from = models.ForeignKey('self',blank=True,null=True,related_name="referraled_who") 50 51 status_choices = (('signed',u'已报名'), 52 ('unregistered',u'未报名'), 53 ('graduated',u'已毕业'), 54 ('drop-off',u'退学'), 55 ) 56 status = models.CharField(choices=status_choices,max_length=64) 57 consultant = models.ForeignKey('UserProfile',verbose_name=u'课程顾问') 58 class_list = models.ManyToManyField('ClassList',blank=True) 59 date = models.DateField(u'咨询日期',auto_now_add=True) 60 61 def __unicode__(self): 62 return "%s(%s)" % (self.qq, self.name) 63 64 65 class CustomerTrackRecord(models.Model): 66 customer = models.ForeignKey(Customer) 67 track_record = models.TextField(u'跟踪记录') 68 tracd_date = models.DateField(auto_now_add=True) 69 follewer = models.ForeignKey(UserProfile) 70 status_choices = ((1,u"近期无报名计划"), 71 (2,u"2个月内报名"), 72 (3,u"1个月内报名"), 73 (4,u"2周内报名"), 74 (5,u"1周内报名"), 75 (6,u"2天内报名"), 76 (7,u"已报名"), 77 ) 78 status = models.IntegerField(u"状态",choices=status_choices,help_text=u"选择客户此时的状态") 79 80 def __unicode__(self): 81 return self.customer 82 83 84 class Course(models.Model): 85 name = models.CharField(max_length=64, unique=True) 86 online_price = models.IntegerField() 87 offline_price = models.IntegerField() 88 introduction = models.TextField() 89 90 def __unicode__(self): 91 return self.name 92 93 94 class ClassList(models.Model): 95 course = models.ForeignKey(Course,verbose_name=u'课程') 96 semester = models.IntegerField(verbose_name=u'学期') 97 course_type = models.CharField(max_length=64,choices=course_type_choices,default='online') 98 teachers = models.ManyToManyField(UserProfile) 99 start_date = models.DateField() 100 gradate_date = models.DateField() 101 102 def __unicode__(self): 103 return "%s (%s)(%s)" %(self.course.name,self.course_type,self.semester) 104 105 class Meta: 106 unique_together = ('course','semester','course_type') 107 108 109 class CourseRecord(models.Model): 110 class_obj = models.ForeignKey(ClassList) 111 day_num = models.IntegerField(u'第几节课') 112 course_date = models.DateField(auto_now_add=True, verbose_name=u'上课时间') 113 teacher = models.ForeignKey(UserProfile) 114 115 def __unicode__(self): 116 return '%s, %s' % (self.class_obj, self.day_num) 117 118 class Meta: 119 unique_together = ('class_obj','day_num') 120 121 122 class StudyRecord(models.Model): 123 course_record = models.ForeignKey(CourseRecord) 124 student = models.ForeignKey(Customer) 125 record_choices = (('checked', u"已签到"), 126 ('late', u"迟到"), 127 ('noshow', u"缺勤"), 128 ('leave_early', u"早退"), 129 ) 130 record = models.CharField(u"上课纪录", choices=record_choices, default="checked", max_length=64) 131 score_choices = ((100, 'A+'), 132 (90, 'A'), 133 (85, 'B+'), 134 (80, 'B'), 135 (70, 'B-'), 136 (60, 'C+'), 137 (50, 'C'), 138 (40, 'C-'), 139 (0, 'D'), 140 (-1, 'N/A'), 141 (-100, 'COPY'), 142 (-1000, 'FAIL'), 143 ) 144 score = models.IntegerField(u"本节成绩", choices=score_choices, default=-1) 145 date = models.DateTimeField(auto_now_add=True) 146 note = models.CharField(u"备注", max_length=255, blank=True, null=True) 147 148 def __unicode__(self): 149 return "%s,%s,%s" % (self.course_record, self.student, self.record)
更多参数:
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to 上传到哪个位置,更多与image,filepath配合使用
连表结构
- 一对多:models.ForeignKey(其他表)
- 多对多:models.ManyToManyField(其他表)
- 一对一:models.ManyToManyField(其他表)
应用场景:
应用场景: 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择) 例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。 多对多:在某表中创建一行数据是,有一个可以多选的下拉框 例如:创建用户信息,需要为用户指定多个爱好 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
注意:
1.models.py中class设置的数据,本身返回一个类,如果想直接返回某一个字段的值,可以定义__unicode__,比如:
class TypeUser(models.Model): name = models.CharFiled(max_length=32) def __unicode__(self): return self.name
2.在设置ForeignKey时,参数中的第一个参数为表明,需要注意的是,加不加引号有区别,加引号后表的定义顺序可以随便,但不加引号必须按照顺序来
3.多对多,有两种创建方式
- 自建第三张表
-
自动创建,比如:
#自建第三张表 class B2G(models.Model): boy = models.ForeignKey('Boy') girl = models.ForeignKey('Girl') class Boy(models.Model): name = models.CharField(max_length=32) # 吴文煜,王建,王志刚,杜宝强 class Girl(models.Model): name = models.CharField(max_length=32) #自动创建 f = models.ManyToManyField(Boy)
4.queryset:从数据库中提取出来的数据为queryset类型,是Django中的一种特殊类型
w = models.Simp.objects.all() print(w, type(w)) [<Simp: chenc>, <Simp: zan>, <Simp: zhangsan>]<class 'django.db.models.query.QuerySet'>
可以看到,从数据库取出个数据看起来像包含对象的列表。而实际上整个数据为django中的特殊类型QuerySet。
如果需要查看原来的SQL语句,可以使用queryset.query
:
print(w.query)
5.values() 和 vlue_list() 与 all()区别
.all()是取得所有列的数据,可以加.values()取出某一列,每一个元素为一个字典:
obj = model.UserInfo.objects.filter(name='alex').values('id','email') # select id from userinfo where name = 'alex' queryset -> python,Django的类 [{'id':1},{'id': 2},]
values_list(),获取到的元素为一个个元组,也可以加多个参数来获取多列:
obj = model.UserInfo.objects.filter(name='alex').value_list('id','email') # select id from userinfo where name = 'alex' queryset -> python,Django的类 [(1,'1@qq.com'),(2,'alex@11.com'),]
二、表的基本操作
1.基本操作:
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) # models.Tb1.objects.all() # 获取全部 # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # 删 # # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改单条数据
2.进阶操作
利用双下划线将字段和对应的操作连接起来(了不起的双下划线)
# 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset # # models.Tb1.objects.all()[10:20] # group by 去重 values('id')在annotate前面就是为了根据id生成group by #需要固定导入,称为聚合函数 from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) moddels.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('id')).values('id'','name') # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
3.连表操作(了不起的双下划线)
利用双下划线和_set将表之间的操作连接起来
数据库表结构:
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.username class UserInfo(models.Model): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname
一对一操作:
user_info_obj = models.UserInfo.objects.filter(id=1).first() print user_info_obj.user_type print user_info_obj.get_user_type_display() print user_info_obj.userprofile.password user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print user_info_obj.keys() print user_info_obj.values()
一对多操作,类似于一对一:
1、搜索条件使用 __ 连接
2、获取值时使用 . 连接
多对多操作:
user_info_obj = models.UserInfo.objects.get(name=u'拉拉') user_info_objs = models.UserInfo.objects.all() group_obj = models.UserGroup.objects.get(caption='CEO') group_objs = models.UserGroup.objects.all() # 添加数据 #group_obj.user_info.add(user_info_obj) #group_obj.user_info.add(*user_info_objs) # 删除数据 #group_obj.user_info.remove(user_info_obj) #group_obj.user_info.remove(*user_info_objs) # 添加数据 #user_info_obj.usergroup_set.add(group_obj) #user_info_obj.usergroup_set.add(*group_objs) # 删除数据 #user_info_obj.usergroup_set.remove(group_obj) #user_info_obj.usergroup_set.remove(*group_objs) # 获取数据 #print group_obj.user_info.all() #print group_obj.user_info.all().filter(id=1) # 获取数据 #print user_info_obj.usergroup_set.all() #print user_info_obj.usergroup_set.all().filter(caption='CEO') #print user_info_obj.usergroup_set.all().filter(caption='DBA')
其他操作:
# F 使用查询条件的值 # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) # Q 构建搜索条件 from django.db.models import Q # con = Q() # # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1.children.append(('id', 9)) # # q2 = Q() # q2.connector = 'OR' # q2.children.append(('c1', 1)) # q2.children.append(('c1', 10)) # q2.children.append(('c1', 9)) # # con.add(q1, 'AND') # con.add(q2, 'AND') # # models.Tb1.objects.filter(con) # # from django.db import connection # cursor = connection.cursor() # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon']) # row = cursor.fetchone()
xx_set中的_set
是多对多的固定搭配
三、扩展
自定义上传:
def upload_file(request): if request.method == "POST": obj = request.FILES.get('fafafa') f = open(obj.name, 'wb') for chunk in obj.chunks(): f.write(chunk) f.close() return render(request, 'file.html')
form上传文件实例
class FileForm(forms.Form): ExcelFile = forms.FileField()
models.py
from django.db import models class UploadFile(models.Model): userid = models.CharField(max_length = 30) file = models.FileField(upload_to = './upload/') date = models.DateTimeField(auto_now_add=True)
view.py
def UploadFile(request): uf = AssetForm.FileForm(request.POST,request.FILES) if uf.is_valid(): upload = models.UploadFile() upload.userid = 1 upload.file = uf.cleaned_data['ExcelFile'] upload.save() print upload.file