标签: D jango 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库,只需要在settings.py中配置即可,不用更改models.py中的代码,丰富的API极大的方便了使用。 # Database # https://docs./en/1.10/ref/settings/#databases # sqlite3数据库连接方式 # DATABASES = { # ‘default‘: { # ‘ENGINE‘: ‘django.db.backends.sqlite3‘, # ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘), # } # } # MySQL数据库连接方式 DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘:‘dbname‘, ‘USER‘: ‘root‘, ‘PASSWORD‘: ‘xxx‘, ‘HOST‘: ‘‘, ‘PORT‘: ‘‘, } } 2、开始创建表 class UserInfo(models.Model): # CharField类型不能为空,最少要指定一个长度 user = models.CharField(max_length=32) email = models.EmailField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey(‘UserType‘) class UserType(models.Model): nid = models.AutoField(primary_key=True) caption = models.CharField(max_length=16) 注:在创建外键的时候直接写上UserType和‘UserType‘的区别就是python程序从上到下解释的顺序问题,如果把UserType这个类写到下面就会没事了 python3 manage.py makemigrations python3 manage.py migrate 创建表的的参数: 1、models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField 字符串字段 必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { ‘SmallIntegerField‘: (-32768, 32767), ‘IntegerField‘: (-2147483648, 2147483647), ‘BigIntegerField‘: (-9223372036854775808, 9223372036854775807), ‘PositiveSmallIntegerField‘: (0, 32767), ‘PositiveIntegerField‘: (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField 图片 24、models.FilePathField 文件 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 执行成功状态: 1 bogon:django_modes01 zk$ python3 manage.py makemigrations 2 Migrations for ‘app01‘: 3 app01/migrations/0001_initial.py: 4 - Create model UserInfo 5 - Create model UserType 6 - Add field user_type to userinfo 7 bogon:django_modes01 zk$ python3 manage.py migrate 8 Operations to perform: 9 Apply all migrations: admin, app01, auth, contenttypes, sessions 10 Running migrations: 11 Rendering model states... DONE 12 Applying contenttypes.0001_initial... OK 13 Applying auth.0001_initial... OK 14 Applying admin.0001_initial... OK 15 Applying admin.0002_logentry_remove_auto_add... OK 16 Applying app01.0001_initial... OK 17 Applying contenttypes.0002_remove_content_type_name... OK 18 Applying auth.0002_alter_permission_name_max_length... OK 19 Applying auth.0003_alter_user_email_max_length... OK 20 Applying auth.0004_alter_user_username_opts... OK 21 Applying auth.0005_alter_user_last_login_null... OK 22 Applying auth.0006_require_contenttypes_0002... OK 23 Applying auth.0007_alter_validators_add_error_messages... OK 24 Applying auth.0008_alter_user_username_max_length... OK 25 Applying sessions.0001_initial... OK
如果提示:No changes detected 在MySQL中就可以看到生成的表: 外键关系: 3.开始创建数据 创建数据的时候有两种方式: 第一种方式: obj = models.表名(字段名=‘***‘) obj.save() 第二种方式: models.表名.objects.create(字段名=‘***‘) 在views.py中写入数据: from django.shortcuts import render,HttpResponse from app01 import models # Create your views here. def index(request): # 创建用户类型表 models.UserType.objects.create(caption=‘管路员‘) models.UserType.objects.create(caption=‘普通用户‘) models.UserType.objects.create(caption=‘超级管理员‘) # 创建用户信息表 user_info_dict_1 = {‘user‘: ‘ales‘, ‘email‘: ‘alex@qq.com‘, ‘pwd‘: 123, ‘user_type‘: models.UserType.objects.get(nid=1), } user_info_dict_2 = {‘user‘: ‘eric‘, ‘email‘: ‘eric@qq.com‘, ‘pwd‘: 123, ‘user_type_id‘: 2, } models.UserInfo.objects.create(**user_info_dict_1) models.UserInfo.objects.create(**user_info_dict_2) print(‘yes‘) return HttpResponse(‘ok‘) 运行Django 项目访问指定文件创建数据: 4、了不起的双下划线之外键正向查找和基本操作 1 # 增 2 # 3 # models.Tb1.objects.create(c1=‘xx‘, c2=‘oo‘) 增加一条数据,可以接受字典类型数据 **kwargs 4 5 # obj = models.Tb1(c1=‘xx‘, c2=‘oo‘) 6 # obj.save() 7 8 # 查 9 # 10 # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) 11 # models.Tb1.objects.all() # 获取全部 12 # models.Tb1.objects.filter(name=‘seven‘) # 获取指定条件的数据 13 14 # 删 15 # 16 # models.Tb1.objects.filter(name=‘seven‘).delete() # 删除指定条件的数据 17 18 # 改 19 # models.Tb1.objects.filter(name=‘seven‘).update(gender=‘0‘) # 将指定条件的数据更新,均支持 **kwargs 20 # obj = models.Tb1.objects.get(id=1) 21 # obj.c1 = ‘111‘ 22 # obj.save() # 修改单条数据
1 # 获取个数 2 # 3 # models.Tb1.objects.filter(name=‘seven‘).count() 4 5 # 大于,小于 6 # 7 # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 8 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 9 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 10 11 # in 12 # 13 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 14 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 15 16 # contains 17 # 18 # models.Tb1.objects.filter(name__contains="ven") 19 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 20 # models.Tb1.objects.exclude(name__icontains="ven") 21 22 # range 23 # 24 # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and 25 26 # 其他类似 27 # 28 # startswith,istartswith, endswith, iendswith, 29 30 # order by 31 # 32 # models.Tb1.objects.filter(name=‘seven‘).order_by(‘id‘) # asc 33 # models.Tb1.objects.filter(name=‘seven‘).order_by(‘-id‘) # desc 34 35 # limit 、offset 36 # 37 # models.Tb1.objects.all()[10:20] 38 39 # group by 40 from django.db.models import Count, Min, Max, Sum 41 # models.Tb1.objects.filter(c1=1).values(‘id‘).annotate(c=Count(‘num‘)) 42 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
单表查询: # ret = models.UserType.objects.all() # print(ret.query) # ret.query后台返回的是查询的sql语句 结果: SELECT `app01_usertype`.`nid`, `app01_usertype`.`caption` FROM `app01_usertype` 获取查询结果的类型: ret = models.UserType.objects.all() print(type(ret), ret) 结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserType: UserType object>, <UserType: UserType object>, <UserType: UserType object>]> 可以看到类型是一个QuerySet类型,后面是所有的对象,每一个元素就是一个对象,可以循环拿出每一次的数据: ret = models.UserType.objects.all() print(type(ret), ret) for item in ret: print(item) 其结果就是每一次循环出来的结果的对象: UserType object UserType object UserType object 每一个对象都代表一个数据,要出去这些数据如下: ret = models.UserType.objects.all() print(type(ret), ret) for item in ret: print(item, item.nid, item.caption) 取出的结果: UserType object 1 管路员 UserType object 2 普通用户 UserType object 3 超级管理员 从结果看出每次输出item的时候都是一个对象(一行数据中所有的对象,对象中封装了所有的数据),在modes中有__str__方法(返回什么,就输出什么,就是查看方便), 在python2.7中叫__unicode__如果在UserType这个类里面使用这个方法: class UserType(models.Model): nid = models.AutoField(primary_key=True) caption = models.CharField(max_length=16) def __str__(self): return ‘%s-%s‘ % (self.nid, self.caption) 然后重新访问下: 1-管路员 1 管路员 2-普通用户 2 普通用户 3-超级管理员 3 超级管理员 就可以看到每一个对象都看到了返回的相对应的参数了。 查询单个字段: ret = models.UserType.objects.all().values(‘nid‘) print(type(ret), ret) 结果查询出nid字段对应的所有的数据 : <class ‘django.db.models.query.QuerySet‘> <QuerySet [{‘nid‘: 1}, {‘nid‘: 2}, {‘nid‘: 3}]> 可以看查询的sql语句,用query方法: ret = models.UserType.objects.all().values(‘nid‘) print(type(ret), ret.query) 查询的结果: <class ‘django.db.models.query.QuerySet‘> SELECT `app01_usertype`.`nid` FROM `app01_usertype` 当通过values循环取值的时候,如下: ret = models.UserType.objects.all().values(‘nid‘) print(type(ret), ret.query) for item in ret: print(item, type(item)) 结果: <class ‘django.db.models.query.QuerySet‘> SELECT `app01_usertype`.`nid` FROM `app01_usertype` {‘nid‘: 1} <class ‘dict‘> {‘nid‘: 2} <class ‘dict‘> {‘nid‘: 3} <class ‘dict‘> 通过结果可以看出,最外部是QuerySet,内部元素封装了一个是封装了这一行所有数据的对象,另外只拿到了某几列的字典! 当通过values_list循环取值的时候,如下: ret = models.UserType.objects.all().values_list(‘nid‘) print(type(ret), ret) 查询结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [(1,), (2,), (3,)]> 依然是queryset,但是结果就是列表中包含的元组,values和values_list的区别就是:values取的是字典类型,values_list把内部元素变成元组了。通过for循环更直观,如下: ret = models.UserType.objects.all().values_list(‘nid‘) print(type(ret), ret) for item in ret: print(type(item), item) 结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [(1,), (2,), (3,)]> <class ‘tuple‘> (1,) <class ‘tuple‘> (2,) <class ‘tuple‘> (3,) 连表查询: 连表查询的时候和sqlachemy有多不同,django没有join这个方法: 通过UserInfo做连表查询 ret = models.UserInfo.objects.all() print(type(ret), ret) for item in ret: print(item, item.user_type, item.id, item.email, item.user, item.pwd) 查询结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> UserInfo object UserType object 1 alex@qq.com ales 123 UserInfo object UserType object 2 eric@qq.com eric 123 首先输出的是查找出来的UserInfo用户信息表,封装了用户所有的信息,而UserType就是一个对象,这个对象里封装的就是一行信息对应的字段(nid和caption),取出UserType对应的信息,例如: ret = models.UserInfo.objects.all() print(type(ret), ret) for item in ret: print(item, item.user_type, item.id, item.email, item.user, item.pwd) print(item.user_type.nid, item.user_type.caption) 取出的UserType对应的信息结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> UserInfo object UserType object 1 alex@qq.com ales 123 UserInfo object UserType object 2 eric@qq.com eric 123 1 管路员 2 普通用户 可以直接取出对应外键的那一列user_type_id: ret = models.UserInfo.objects.all() print(type(ret), ret) for item in ret: print(item, item.user_type, item.id, item.email, item.user, item.pwd) print(item.user_type.nid, item.user_type.caption, item.user_type_id) 结果: <class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> UserInfo object UserType object 1 alex@qq.com ales 123 1 管路员 1 UserInfo object UserType object 2 eric@qq.com eric 123 2 普通用户 2 如果只想看到数据对应的名称,就需要加映射values: ret = models.UserInfo.objects.all().values(‘user‘, ‘user_type__caption‘) print(ret, ret.query) 结果: <QuerySet [{‘user‘: ‘ales‘, ‘user_type__caption‘: ‘管路员‘}, {‘user‘: ‘eric‘, ‘user_type__caption‘: ‘普通用户‘}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) 通过结果可以看到user_type__caption可以跨表直接获取相应的结果,再看sql语句中django本身加上了一个join。 如果在models中在加上一个表"P",然后在UserType中增加一条外键指向"平"P",需求:要查找UserInfo表中的name和UserType表中的caption和P表中的neme的方法就是在找下一个对象的时候继续加双下划线: 增加的表结构: 查询语法: ret = models.UserInfo.objects.all().values(‘user‘, ‘user_type__caption‘, ‘user_type__p__name‘) print(ret, ret.query) 查询的结果: <QuerySet [{‘user_type__p__name‘: ‘allan‘, ‘user_type__caption‘: ‘管路员‘, ‘user‘: ‘ales‘}, {‘user_type__p__name‘: ‘allan‘, ‘user_type__caption‘: ‘普通用户‘, ‘user‘: ‘eric‘}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption`, `app01_p`.`name` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) INNER JOIN `app01_p` ON (`app01_usertype`.`p_id` = `app01_p`.`id`) 如果要拿用户类型是管理员的所有用户: ret = models.UserInfo.objects.filter(user_type__caption="管路员").values(‘user‘, ‘user_type__caption‘) print(ret) 结果: <QuerySet [{‘user‘: ‘ales‘, ‘user_type__caption‘: ‘管路员‘}]> 5、了不起的上下划线值外键反向查找 找到管理员相关联的信息: obj = models.UserType.objects.filter(caption=‘管理员‘).first() print(obj.nid, obj.caption) 输出结果: 1 管理员 这里查找的是usertype中的数据,如果通过usertype表查找到userinfo表中的信息就得用***_set: obj = models.UserType.objects.filter(caption=‘管理员‘).first() print(obj.nid, obj.caption) print(obj.userinfo_set.all()) ret = models.UserType.objects.all().values(‘nid‘, ‘caption‘, ‘userinfo__user‘) print(ret) 查询结果: 1 管理员 <QuerySet [<UserInfo: UserInfo object>]> <QuerySet [{‘caption‘: ‘管理员‘, ‘userinfo__user‘: ‘alex‘, ‘nid‘: 1}, {‘caption‘: ‘普通用户‘, ‘userinfo__user‘: ‘eric‘, ‘nid‘: 2}, {‘caption‘: ‘超级管理员‘, ‘userinfo__user‘: None, ‘nid‘: 3}]> [27/Aug/2016 15:35:31] "GET /index/ HTTP/1.1" 200 2 如果需要固定字段查找: obj = models.UserType.objects.all().values(‘nid‘, ‘userinfo__user‘) print(obj) 结果: <QuerySet [{‘userinfo__user‘: ‘alex‘, ‘nid‘: 1}, {‘userinfo__user‘: ‘eric‘, ‘nid‘: 2}, {‘userinfo__user‘: None, ‘nid‘: 3}]> 6、多对多之表创建 多对多创建表的时候直接使用ManyToManyField让django自动创建第三张表或者自己手动创建第三张表,第三张表如果指定多个字段的hu models表结构(自定义的第三张表): class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=32) class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16) h2g = models.ManyToManyField(‘Host‘, through=‘HostToGroup‘) class HostToGroup(models.Model): hgid = models.AutoField(primary_key=True) host_id = models.ForeignKey(‘Host‘) group_id = models.ForeignKey(‘Group‘) status = models.IntegerField() 插入数据: models.Host.objects.create(hostname=‘c1‘, ip=‘1.1.1.1‘) models.Host.objects.create(hostname=‘c2‘, ip=‘1.1.1.2‘) models.Host.objects.create(hostname=‘c3‘, ip=‘1.1.1.3‘) models.Host.objects.create(hostname=‘c4‘, ip=‘1.1.1.4‘) models.Host.objects.create(hostname=‘c5‘, ip=‘1.1.1.5‘) models.Group.objects.create(name=‘技术部‘) models.Group.objects.create(name=‘财务部‘) models.Group.objects.create(name=‘人事部‘) models.Group.objects.create(name=‘公关部‘) models.Group.objects.create(name=‘运营部‘) models.Group.objects.create(name=‘销售部‘) models.Group.objects.create(name=‘客服部‘)
操作表: 获取财务部的对象: obj = models.Group.objects.get(gid=2) print(obj.gid, obj.name, obj.h2g.all()) 结果: 2 财务部 <QuerySet []> 给财务部添加主机: # 添加一台主机 obj = models.Group.objects.get(gid=2) # print(obj.gid, obj.name, obj.h2g.all()) h1 = models.Host.objects.get(hid=1) obj.h2g.add(h1) # 把剩下的全部添加 obj = models.Group.objects.get(gid=2) # print(obj.gid, obj.name, obj.h2g.all()) # h1 = models.Host.objects.get(hid=1) q = models.Host.objects.filter(hid__gt=1) obj.h2g.add(*q)
将一台机器分配给多个组(就得用反向操作了): h = models.Host.objects.get(hid=1) h.group_set.add(*models.Group.objects.filter(gid__gt=2))
操作自己手动创建的第三张关系表: 表结构: 表的数据还是原来的数据。 创建表之间的关系,需要自己手动创建关系: models.HostToGroup.objects.create(status=1, group_id_id=2, host_id_id=3)
标签: 原文地址:http://www.cnblogs.com/allan-king/p/5807659.html |
|