Django数据模型(models)
序言
由于先天具备Python简单而强大的数据库查询执行方法,Django非常适合开发数据库驱动网站。Django模型即Django数据库层。
Django 遵循MVC模式(Model-View-Controller):
- M , 数据存取部分,由Django数据库层处理
- V , 选择显示哪些数据,由视图和模板处理
- C , 根据用户输入委派视图的部分,由URLconf设置,对于给定URL调用适当的Python函数
由于 C 由框架自行处理,而Django更加关注的是模型(Model),模板(Template)和视图(Views),Django也被称为MTV架构。
在MTV开发模式中:
- M, 代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如果存取,如何验证有效性,包含哪些行为以及数据之间的关系等。
- T , 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
- V , 代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。可以看做是模型和模板之间的桥梁。
1. 基本命令
# 数据库相关命令 python manage.py validate # 验证模型的有效性,validate 命令检查你的模型语法和逻辑是否正确,如果一切正常,你会看到0 errors found. python manage.py sqlall app名称 # 输出models中数据库建库语句(以sql的方式输出) python manage.py syncdb # 同步你的模型到数据库的一个简单方法,他会通过INSTALLED_APPS里设置的app来检查数据库,如果表不存在则创建,需要注意的是,sync并不能将模型的修改或删除同步到数据库,如果你修改或删除一个模型,用syncdb提交,不会做任何处理。 python manage.py makemigrations # Django 1.7.1以上版本使用,代替syncdb,生成一个数据库结构migrations里面的一个表 python manage.py migrate # 根据migrations里面的表创建数据库 python manage.py flush # 清除数据库 python manage.py dumpdata appname > appname.json # 导出数据库 python manage.py loaddata appname.json # 导入数据库 python manage.py dbshell # 进入数据库
2.类的结构
(1)基础类型
from django.db import models
class userinfo(models.Model): # 这个类是用来生成数据库表的,必须继承models.Model
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
(2)连表类型
一对多:models.ForeignKey("其他表")
多对多:models.ManyToManyField("其他表")
一对一:models.OneToOneField("其他表")
应用场景: * 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被视为重复选择) # 示例:创建用户时,选择用户类型 * 多对多:在某表中创建一行数据时,有一个可以多选的下拉框 # 示例:创建用户时,用户指定的多个爱好 * 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失) # 示例:表里有10列数据,一段时间后需要添加5列
(3)字段类型
常用字段说明: * AutoField :自增列,如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 * BigAutoField :bigint 自增列,64位整数,1到9223372036854775807。必须参数:primary_key=True * SmallIntegerField :小整数,范围 -32768~35767 * PositiveSmallIntegerField :正整数,范围:0~32767 * PositiveIntegerField :正整数,范围:0~2147483647 * IntegerField :整数列(有符号),范围:-2147483648~2147483647 * BigIntegerFiled :长整型(有符号的)-9223372036854775808~9223372036854775807 * BooleanField :布尔值,不能为空,如果没有定义默认值,则默认为None * NullBooleanField :可以为空的布尔值 * CharFiled : 字符串类型,必须提供max_length参数,表示字符长度 * TextField :文本类型,大文本字段 * EmailField :本质上依然是字符串类型,在django admin和ModelForm中提供邮箱格式验证 * IPAddressField :字符串类型,提供IPV4验证,高版本中可能会报错,被下面的替代 * GenericIPAddressFiled :字符串类型,提供ipv4和ipv6两种验证 * GenericIPAddressField(protocol='both', unpack_ipv4=False,**opthions) * 参数:protocol,用于指定ipv4和ipv6,默认是both表示两者都选,匹配不区分大小写 * 参数:unpack_ipv4,压缩ipv4映射地址::ffff:192.0.2.1将被压缩为192.0.2.1。默认为禁用,只能在protocol设置时使用'both' * URLField :字符串类型,django提供URL验证 * SlugField :字符串类型,django提供验证,支持字母,数字,下划线,连接符 * ComaSeparatedIntegerField :字符串类型,格式必须是逗号分隔的数字. 继承了CharField,所以必须有max_length参数 * UUIDField :字符串类型,django提供对UUID格式的验证 * id = modles.UUIDField(primary_key=True,default=uuid.uuid4, editable=False) * FilePathField :字符串类型,django提供读取文件夹下文件的功能 * FilePathField(path=None,match=None,recursive=False,max_length=100, **options) * 示例:models.FilePathField(path="/home/file", match="foo.*", recursive=True) * path:文件夹路径 * match:正则匹配 * recursive:递归下面的文件夹 * allow_files=True:允许文件 * allow_folers=False:允许文件夹 * FileField :字符串,路径保存在数据库,文件上传到指定目录,两个可选参数 * upload_to = "" 上传文件的保存路径 * upload = models.FileField(upload_to='uploads/') # 第一种是上传到指定目录 * upload = models.FileField(upload_to='uploads/%Y/%m/%d/') # 第二种是上传到一个目录下的当前时间日期目录(uploads/2017/05/04)这种,方便管理。 * storage = None 存储组件,默认django.core.files.storage.FileSystemStorage * ImageField :字符串,路径保存在数据库,文件上传到指定目录 * upload_to = "" 上传保存路径 * storage = None 存储组件 * width_field=None ,上传图片的宽度(字符串) * height_field=None, 上传图片的高度(字符串) * DateTimeField :日期+时间格式 YYYY-MM-DD HH:MM [:ss[.uuuuu]][TZ] * auto_now = True, 更新时间,每次更新都会自动更新 * auto_now_add = True , 创建时间,不会更新 * DateField :日期格式, YYYY-MM-DD * auto_now = True, 更新时间,每次更新都会自动更新 * auto_now_add = True , 创建时间,不会更新 * TimeField :时间格式,HH:MM [:ss[.uuuuu]] * DurationField :长整型,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta * FloatField :浮点型 * DecimalField :10进制小数 * max_digits : 小数总长度 * decimal_places :小数位长度 * BinaryField :二进制类型,它支持bytes.这个字段功能有限,不能在此字段值上做过滤查询,也不能用于ModelForm。
(4)参数类型
1、null=True 数据库中字段是否可以为空
2、blank=True django的 Admin 中添加数据时是否可允许空值
3、primary_key = True 主键,对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配合使用
表操作
(1)基本操作
# 增 (1)第一种 models.Tb1.objects.create(c1='xx', c2='oo') # 向Tb1表增加一条数据,可以接受字典类型数据 **kwargs (2)第二种 obj = models.Tb1(c1='xx', c2='oo') obj.save() # 查 models.Tb1.objects.get(id=123) # 获取Tb1表中id=123的数据,不存在则报错(不建议使用) models.Tb1.objects.all() # 获取Tb1表的全部数据 models.Tb1.objects.filter(name='alex') # 获取指定条件的数据 # 删 models.Tb1.objects.filter(name='alex').delete() # 删除指定条件的数据 # 改 models.Tb1.objects.filter(name='alex').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs obj = models.Tb1.objects.get(id=1) obj.c1 = '111' obj.save() # 修改单条数据
(2)进阶操作(了不起的双下划线)
# 获取个数
models.Tb1.objects.filter(name='alex').count()
# 大于,小于
models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
models.Tb1.objects.filter(id__lt=0 # 获取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") # 获取name包含ven的数据
models.Tb1.objects.filter(name__icontains="ven") # icontains不区分大小写
models.Tb1.objects.exclude(name__icontains="ven") # 获取name字段不包含ven的数据
# range
models.Tb1.objects.filter(id__range=[1,2]) # 范围bettwen and
# 其他类似
startswith # 字段以什么开头
istartswith # 字段非以什么开头
endswith # 字段以什么结尾
iendswith # 字段非以什么结尾
# order by
models.Tb1.objects.filter(name="alex").order_by('id') # asc 升序
models.Tb1.objects.filter(name="alex").order_by('-id') # desc 降序
# limit, offset
models.Tb1.objects.all()[10:20] # 获取Tb1表中第10条到第20条数据
# group by
from django.db.models import Conut, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
# F 使用查询条件的值
from django.db.models import F
models.Tb1.objects.update(num=F('num')+1) # F('num') 获取数据库中当前字段的值,即所有num字段的值增加1
# Q 构建搜索条件
# filter()中可以传递,k:value, **dict, 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) # 搜索的结果需要同时满足q1和q2
# 在django里之间使用SQL语句
from django.db import connection
cursor = connection.cursor()
cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
row = cursor.fetchone()
(3)连表操作
利用双下划线和_set 将表之间的操作连接起来
# models.py 表结构 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() # 获取用户id为1的用户数据 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、搜索条件使用 __ 连接 UserInfo 记录用户name,pwd UserType记录用户类型 models.UserInfo.objects.filter(user_type__name='CEO') # 获取用户类型是CEO的所有用户信息 2、获取值时使用 . 连接 models.UserInfo.objects.filter(user_type__name='CEO').values('name','pwd','user_type__name') [{'name':'user1','pwd':'password','user_type__name':'CEO'}] # 如果将values 换成 value_list,获取的结果将变成元组 [(xx,xx,xx)]
# 多对多操作 # xx_set 中的【_set】是多对多中的固定搭配 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'))
。。

浙公网安备 33010602011771号