Django学习之 - 基础ORM
ORM操作
参考: http://www.cnblogs.com/wupeiqi/articles/5246483.html
1:根据类自动创建数据库表,(类创建文件:models.py)
2:根据类对数据库表中的数据进行各种操作
创建类
a:先写类
# 创建的表名为:cmdb_userinfo
class UserInfo(models.Model):
# 生成表时候会自动创建id列,此列为自增,主键
# 用户名列,字符串类型,指定长度
# 字段类型包含:字符串,数字,时间,二进制
# 字段的参数:
字段参数:
null=True, # db是否可以为空
default='1111', # 默认值
db_column # 指定表中的列的名称
db_index=True, # 在当前字段建立索引
unique=True, # 唯一索引
unique_for_date # 对时间做索引
unique_for_month # 对月份做索引
unique_for_year # 对年份做索引
max_length=xxx # 表示字符长度
primary_key= True # 主键
auto_now # 更新时,自动更新为当前时间
注意:这里的更新需要特定的条件,写法如下:
obj = UserGroup.objects.filter(id=1).first()
obj.caption = 'CEO'
obj.save()
以下这种写法不会生效:
UserGroup.objects.filter(id=1).update(caption='CEO')
auto_now_add # 创建时,自动生成时间
DjangoAdmin提供的参数:
verbose_name Admin页面中显示的字段名称
blank=true Admin页面数据库中是否允许用户输入为空
editable=true Admin页面中是否可以编辑字段,false的话将不显示字段
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作,避免连表查询。
如:user_type_choices=(
(1,'超级用户),
(2,'普通用户),
(3,'来宾用户),
)
user_type_id = models.IntegerField(choices=user_type_choices,default=1)
这样在页面上显示的此项数据是个选择框显示
error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
# 创建自增列方法:
uid = models.AutoField(primary_key = True)
注意:mysql表里只能有一个自增列
说明:创建列指定类型有:EmailField,URLField,GenericIPAddressField等都是针对admin的web页面使用限制,对于数据库内
全部是CharField类型标识。
b:注册APP,要在setting里添加app名称
c:执行命令:
1:python manage.py makemigrations
2:python manage.py migrate
另:在对原表的字段属性修改后运行上面命令就可以修改表属性
如果对表增加一列后,运行上面命令。默认情况下会出现一个提示,让输入新增加列的默认值,输入完成后在运行即可添加一列。
如果我们不想手工输入值,需要在新增加的列属性中添加 null=True,这样运行命令后即可增加一个空列。
d:注意:django默认连接mysql使用的MysqlDB,python3里没有此模块,要使用pyMysql,需要修改项目下的init文件。
加入如下代码:
import pymysql
pymysql.install_as_MySQLdb()
数据 增/删/改/查
# 创建
# 第一种 -推荐使用
# models.UserInfo.objects.create(username='root',password='123')
# 另一种写法
# dic = {'username':'jack','password':'333'}
# models.UserInfo.objects.create(**dic)
# 第二种
# obj = models.UserInfo(username='root',password='123')
# obj.save()
# 查询
# result = models.UserInfo.objects.all() # 获取表所有数据
# result = models.UserInfo.objects.get(username='root') # 获取单条数据
# result = models.UserInfo.objects.filter(username='root') # 指定条件查询
# result = models.UserInfo.objects.filter(username='root',password='123') # 多条件查询
# result = models.UserInfo.objects.filter(username='root').first() # 从查询结果列表中提取第一个值以obj输出
# result = models.UserInfo.objects.filter(username='root').count() # 查询匹配条件数量
# result = models.UserInfo.objects.exclude(username='root') # 指定条件反向查询(非)
# 这里查到的result也是对象
# # 返回的result是django提供的QuerySet类型。就是个列表,每行数据是个对象,
# # [obj,obj...],对象obj包含(id,username,password)
# print(result)
# for i in result:
# print(i.id,i.username,i.password)
n1 = models.Business.objects.all() # 取所有
# QuerySet类型,内部元素都是对象
n2 = models.Business.objects.all().values('id','caption') # 取固定列
# QuerySet类型,内部元素都是字典
n3 = models.Business.objects.all().values_list('id','caption') # 取固定列
# QuerySet类型,内部元素都是元祖
models.Business.objects.filter(id=1).first()
# 获取到的是一个对象
# 删除
# models.UserInfo.objects.all().delete() # 删除所有
# models.UserInfo.objects.filter(id=3).delete() # 删除所有
# 修改
# models.UserInfo.objects.all().update(password="666") # 修改所有
# models.UserInfo.objects.filter(id=1).update(password='5432') # 修改一条
# obj = models.UserInfo.objects.get(id=1) # 修改一条数据
# obj.password = '123'
# obj.save()
其他补充
# models.UserInfo.objects.filter(id__gt=1) 获取ID大于1的值
# models.UserInfo.objects.filter(id__gte=1) 获取ID大于等1的值
# models.UserInfo.objects.filter(id__lt=1) 获取ID小于1的值
# models.UserInfo.objects.filter(id__lte=1) 获取ID小于等于1的值
# models.UserInfo.objects.filter(id__gt=1,id__lt=10) 获取ID大于1小于10的值
# models.UserInfo.objects.filter(id__in=[11,22,33]) 获取ID等于11,22,33的数据
# models.UserInfo.objects.exclude(id__in=[11,22,33]) 获取ID不等于11,22,33的数据
# models.UserInfo.objects.filter(name__isnull=True) 查询name为空的
# models.UserInfo.objects.filter(name__contains='ven') 查询name名称包含ven的值
# models.UserInfo.objects.exclude(name__contains='ven') 查询name名称不包含ven的值
# models.UserInfo.objects.filter(name__icontains='ven') 不区分大小写,功能根据具体数据库而定
# models.UserInfo.objects.filter(id__range=[1,10] 范围查询,查询ID在1到10之间的数据,还有startswith,endswith
# models.UserInfo.objects.filter(name='seven').order_by('id') 正向排序,asc
# models.UserInfo.objects.filter(name='seven').order_by('-id') 反向排序,desc
# models.UserInfo.objects.all()[10:20] 进行分页,就是切片
# models.UserInfo.objects.get(name__regex-r'^(An?|The) +') regex正则匹配,iregex不区分大小写
# models.UserInfo.objects.filter(pub_date__date=datetime.date(2005,1,1)) 匹配日期查找
# models.UserInfo.objects.filter(pub_date__date__gt=datetime.date(2005,1,1)) 大于匹配日期查找
# models.UserInfo.objects.filter(pub_date__year=2005) 匹配年
# models.UserInfo.objects.filter(pub_date__month=12) 匹配月
# models.UserInfo.objects.filter(pub_date__day=3) 匹配日
# models.UserInfo.objects.filter(pub_date__week_day=2) 匹配星期
# models.UserInfo.objects.filter(timestamp__hour=23) 匹配小时
# models.UserInfo.objects.filter(timestamp__minute=29) 匹配分钟
# models.UserInfo.objects.filter(timestamp__second=31) 匹配秒
from django.db.models import Count(个数),Min(最小),Max(最大),Sum(总和)
models.Tbl.objects.filter(c1=1).values('id').annotate(c=Count('num')) 分组操作,filter(c1=1)到这里为第一步筛选,之后是
根据values('id')进行分组,最后c=Count('num')是获取每个组的个数
# models.UserInfo.objects.only('id','name') 仅执行一次查询获取id和name列,
# models.UserInfo.objects.defer('id','name') 仅执行一次查询排除id和name列,
# models.UserInfo.objects.all().order_by('-nid').reverse() 当order_by,reverse同时存在则倒序
using() 指定使用数据库,参数为别名(setting中设置),可用作数据库读写分离。
querySET补充额外的操作方法
extra:构造额外的查询条件或者映射,如:子查询
def extra(self,select=None,where=None,param=None,tables=None,order_by=None,select_params=None)
tablename.object.filter().extra(select={'cid':1})
tablename.object.filter().extra(select={'cid':"%s"},select_params=[1])
tablename.object.filter().extra(select={'nid':"select col from tbl where oth=%s"},select_params=1)
tablename.object.filter().extra(select={'nid':"func(id)"})
tablename.object.filter().extra(where=['headline=1','nid>1']) # 这2个条件以and联合
tablename.object.filter().extra(where=['headline=1 or nid=1']) # 这2个条件以and联合
tablename.object.filter().extra(where=['func(ctime)=1 or nid=%s'],param=['1']) # 加入函数
Django数据库优化:
与性能相关的2个方法:select_related(跨表查询数据只一次性),prefetch_related(数据库查询执行2次)
1:select_related
users = models.User.object.all() 跨表查
for row in users:
print(row.user)
print(row.ut.name)
# 这样性能较差,假如10行数据第一次查询执行了1次数据库操作,在循环里每次到ut.name跨表查询时候都要执行一次数据库操作,
# 这样,一共下来得执行11次数据库操作。优化写法:models.User.object.all().select_related('ut'),这样就只发一次数据库请求,
# 参数只能指定ForignKey字段,当有多个外键字段时候,通过指点外键,将只查询指定字段的关联数据。
users = models.User.object.all().values('user','ut__name')
# 这种方式取回的是个字典,就不可以使用querySet功能了。这也是一个缺点。
2:prefetch_related #2次查询会生成2张表,django会做2张表的关系,提取数据写法不变。
users = models.User.object.filter(id__gt=30).prefetch_related('ut')
# 第一次查询:select * from user where id > 30 获取结果ut_id=[1,2]
# 第二次查询:select * from usertype where id in [1,2] 匹配id为1或2 的数据类型
for row in users:
print(row.name)
print(row.ut.name)
dates(field_name,kind,order='ASC':截取指定时间内容
kind: year(年),month(年月),day(年月日)
models.DatePlus.objects.dates('ctime','day','DESC') 第一个参数:列名,第二个参数是指定截取内容(比如时间数据包含年月日时分秒,
这里使用day,就会进行截取到年月日为止,可选参数:year,month,day),第三个参数:排序(ASC,DESC)
datetimes(field_name,kind,order='ASC',tzinfo=None):截取指定时间内容,并将时间转换为时区时间
kind:year,month,day,hour,minute,second
tzinfo: 时区对象
models.DatePlus.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
models.DatePlus.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
需要安装个时区模块(pytz);import pytz / pytz.all_timezone / pytz.timezone('...')
raw(raw_query,params=None,translations=None,using=None):执行原生的sql语句
models.User.object.raw('select * from User') 输出的是多个对象,每列数据全部封装到对象里
models.User.object.raw('select nid as id from User2') 将user2中的nid列赋值给user表的id
通过对应关系进行赋值,如先定义一个字典:dic={'id':'nid','name':'username'}
models.User.object.raw('select * from User2',dic) # 通过字典做映射
注意:映射必须要有主键
models.User.object.raw('select * from User',using='default 指定数据库')
aggregate:整个表整体做聚合
from django.db.models import Count(数量),Avg,Max,Min,Sum(数据总和)
models.User.objects.aggregate(n=Count('nid',distinct=True(这个功能是去重))) 求表中nid列所有数据的个数总和
bulk_create:批量插入。 参数batch_size=None 表示一次插入的数量
objs={ models.ddd(name='r1'),models.ddd(name='r2')}
models.DDD.objects.bulk_create(objs,10) # 一次插入10条数据
get_or_create(default=None,**kwargs):如果存在则获取,不存在则创建
obj,created = models.User.objects.get_or_create(uname='root',default={'email':'1@mail.com','u_id':2}
这里的default是当创建的时候使用此参数,查询的时候是调用uname即可。返回2个值,第一个是返回的对象,第二个是状态。
update_or_create(default=None,**kwargs):如果存在则更新,否则,创建
models.User.objects.get_or_create(uname='root',default={'email':'1@mail.com','u_id':2}
in_bulk:根据主键ID进行查找
exists:是否有结果。
外键:(一对多)
现有表:user 和 表:group
在表user 增加外键如下:
usergroup = models.ForeignKey('group 表group名称',to_field='id group表的唯一键',default=1 当创建用户的时候,指定用户的默认组)
简单说明:user表的外键usergroup 就是封装了group表,调用方式;
user.usergroup == group表queryset对象
user.usergroup.id == group.id 等等
如果group表也有外键关联其他表,调用关系是一样的,如:
user.usergroup.group外键.关联表的字段名
增/删/该/查同上
1:载入页面提取组信息:grouplist = models.group.objects.all()
2:页面输入数据选择组后提交
3:后台获取选择的组ID后写库
models.user.objects.create(....usergroup=组ID)
# 外键通过点 . 进行跨表查询
一对多跨表操作的3种方式
v1 = models.Host.objects.filter(nid__gt=0)
# 这里通过Print取值使用点.进行跨表取值
v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')
# 进行跨表查询是通过双下划线__ 进行
v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','b_id','b__caption')
# 进行跨表查询是通过双下划线__ 进行
多对多:
创建多对多:
方式一:自定义关系表,关联表可以自定义多列。
class host(models.Model):
nid=models.AutoField(primary_key=True)
hostname=models.CharField(max_length=32,db_index=True)
ip=models.GenericIPAddressField(protocol='both/ipv4',db_index=True)
port=models.IntegerField()
b = models.ForeignKey('Business',to_field='id')
class Application(models.Model):
name = models.CharField(max_length=32)
class HostToApp(models.Model):
hobj=models.ForeignKey(to='host',to_field='nid')
aobj=models.ForeignKey(to='Application',to_field='id')
关联表添加数据方式:
HostToApp.objects.create(hobj_id=1,aobj_id=2)
方式二:自动创建关系表,生成的关联表只有3列生成。
class host(models.Model):
nid=models.AutoField(primary_key=True)
hostname=models.CharField(max_length=32,db_index=True)
ip=models.GenericIPAddressField(protocol='both/ipv4',db_index=True)
port=models.IntegerField()
b = models.ForeignKey('Business',to_field='id')
class Application(models.Model):
name = models.CharField(max_length=32)
r=models.ManyToManyField("host")
# 无法直接对第三张关联表操作
obj = Application.objects.get(id=1)
obj.name
# 第三张表操作添加
obj.r.add(1) # 第三张表添加关联 1对1
obj.r.add(2,3,4) # 第三张表添加关联 1对2,1对3,1对4
obj.r.add(*[1,2,3,4]) ## 第三张表添加关联 1对1,1对2,1对3,1对4
# 第三张表操作删除
obj.r.remove(1)
obj.r.remove(2,3,4)
obj.r.remove(*[1,2,3,4])
obj.r.clear() # 删除applicaton id=1的所有对应关系
# 第三张表操作修改
obj.r.set([3,5,7]) # 将数据库里application id=1的所有对应关系全部修改为1对3,1对5,1对7
# 第三张表操作查询,
obj.r.all() # 获取到的是所有相关的主机对象"列表",queryset
Django学习之 - 基础ORM的更多相关文章
- Django学习笔记之ORM字段和字段参数
Object Relational Mapping(ORM) 一.ORM介绍 1. ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象 ...
- Django (学习第二部 ORM 模型层)
Django对数据库的操作 Django的 ORM 简介 ORM操作 (增删改查) ORM操作数据库的增删改查 ORM创建表关系 ORM中常用字段及参数 数据库的查询优化 ORM中如何开启事务 ORM ...
- Django学习笔记之ORM多表操作
创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关 ...
- Django学习之 - 基础模板语言
模板语言if/else/endif {% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} &l ...
- Django学习之 - 基础部分
学习记录参考: 讲师博客:http://www.cnblogs.com/wupeiqi/articles/5433893.html 老男孩博客:http://oldboy.blog.51cto.com ...
- Django——6 模型基础ORM 数据库连接配置 模型的创建与映射 数据的增删改查
Django Django的ORM简介 数据库连接配置 模型的创建与映射 数据库的增删改查 增数据 查数据及补充 改数据 删数据 Django的ORM系统分析 ORM概念:对象关系映射(Objec ...
- Django学习之 - 基础视图函数
视图:Views 获取用户请求的方法: 1: request.GET 2: request.POST 3: request.FILES # checkbox 等多选文件 4:request.POST. ...
- Django学习之 - 基础路由系统
路由系统:URL 1:一个URL对应一个类或函数: url(r'^register',reg.register) 函数写法 url(r'^cbv',reg.cbv.as_view()) 类写法 2:通 ...
- Django学习系列之Form基础
Django学习系列之Form基础 2015-05-15 07:14:57 标签:form django 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追 ...
随机推荐
- sql通过 openrowset查询csv文件
两步即可完成 第一步. 创建cmmData.xml文件,并存入到能与sql服务器共享的文件夹中(如:\\10.252.21.6\sharedfolder) <?xml version=" ...
- python笔记_magic变量和函数
前言 先扯一点背景知识 PEP8(Python Enhancement Proposal)是一份python的编码规范,链接:http://www.python.org/dev/peps/pep-00 ...
- Windows程序设计1(工具、编码、窗口)
一.几个常用小工具: 1. 编译器:CL.EXE 将源文件转变为目标文件(汇编语言). CL.EXE /c xxx.c 或 xx.cpp cl.exe -? 显示cl帮助 cl.exe ...
- Android(java)学习笔记174:服务(service)之混合方式开启服务
1. 前面我们已经讲过可以使用两种方式开启服务 startService----stopService: oncreate() ---> onstartCommand() ---& ...
- WPF知识点全攻略01- WPF相对WinFrom的优缺点
对比WPF和WinFrom前,先来了解下GUI现阶段在用的其他一些开发技术: MFC:微软基础类库,以C++的形式封装了Windows API,加上一些实用工具类. QT:奇趣科技开发的跨平台C++图 ...
- jquery--cookie应用
示例:发送手机验证码 防止页面刷新后,发送验证码按钮重置 注:橙色部分为后增加代码,为防止验证码等待期间用户退出或者切换到其他页面以至于很久之后回到当前页面倒计时还在的问题,加入时间对比,记录用户发送 ...
- HashMap和HashTable的理解与区别
Hashtable是java一开始发布时就提供的键值映射的数据结构,而HashMap产生于JDK1.2.虽然Hashtable比HashMap出现的早一些,但是现在Hashtable基本上已经被弃用了 ...
- python基础一 day2
内容: 3%%s 输出:3%s 后面的全部转义 结果: 如果是因为执行break语句导致循环提前结束,就不会执行else. 单位换算: 编码方式: ascii unicode u ...
- Java中System.setProperty()用法
/* * 设置指定键对值的系统属性 * setProperty (String prop, String value); * * 参数: * prop - 系统属性的名称. * value ...
- mysql数据库优化 几个思路
建表: 合理的索引, 组合索引 合理的字段类型 合理的表结构和表关联关系 查询: 避免: *, 函数 , 计算 , like左右全匹配 , in , beteewn?? 索引和组合索引 子查询 ...