• Django学习之


    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

  • 相关阅读:
    162 基于UDP协议的socket套接字编程
    161 解决粘包问题
    160 粘包问题
    159 模拟ssh远程执行命令
    158 Socket抽象层
    157 基于TCP协议的socket套接字编程
    C++:查找字符串字串并替换
    C++:查找字符串字串并替换
    请问c++中的#include "stdafx.h"是什么意思?
    请问c++中的#include "stdafx.h"是什么意思?
  • 原文地址:https://www.cnblogs.com/zy6103/p/7552896.html
Copyright © 2020-2023  润新知