zoukankan      html  css  js  c++  java
  • 六、Django的orm之单表操作

    Django模型层(一)单表操作

    一、ORM

    ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)

    orm其实就是将类对象的语法翻译成sql语句的一个引擎

    类对象 --- sql

    类 -- 表

    对象 -- 行

    属性 -- 字段

    原生sql和Python的orm代码对比:

    二、Django连接数据库

    在Django项目的app应用下,有一个 models.py 文件,就是专门用来写和数据库相关的代码的

    1. app01 应用下 的models.py 文件中,写代码来创建一个表
      from django.db import models

      # 创建表
      class Userinfo(models.Model):
      
          id = models.AutoField(primary_key=True)
          name = models.CharField(max_length=18)
          age = models.IntegerField()
          current_date = models.DateField()
      
      # 相当于:
      # create table userinfo(
      #   id int primary key auto_increment,
      #   name vachar(18),
      #   age int,
      #   current_data date
      # );
      
    2. 不连接mysql的话,默认连接的是sqlite数据库,是一个小型文档数据库,测试的时候可以用一下,但是在实际生产中很少用,而是用mysql
      使用sqlite的数据库:

      第一次运行时,因为没有安装sqlite的驱动,是打不开数据库的

      安装驱动后再次打开,出现下面情况就是运行成功了,会显示我们制作的表结构

      这个时候我们就可以添加数据了

    3. 连接mysql
      在配置文件settings中找到:
      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.sqlite3',
      'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
      }
      }

      # 修改成:
      # 现在终端创建一个库 orm01
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.mysql',
              'HOST': '127.0.0.1',
              'POST': 3306,        #  端口 默认3306
              'NAME': 'orm01',
              'USER': 'root',
              'PASSWORD': '123',
      
          }
      }
      

      然后在项目文件夹下的 init.py 文件中加入这两句话:
      import pymysql
      pymysql.install_as_MySQLdb() # MySQLdb是默认的连接数据库的客户端模块,但是不支持Python3.4以上版本,所以要用pymysql把MySQLdb替换掉

      最后执行数据库同步指令
      python manage.py makemigrations
      python manage.py migrate

      进入cmd终端进入mysql查看我们的表是否插入进去了:

      由此可见,我们插入表的操作算是成功的完成了!!!

    三、ORM表单操作

    (一)、简单的增删改查

    类---表
    类对象 --- 一行数据
    类属性 --- 字段
    

    先创建一张表,定义四个属性:

    class Student(models.Model):
        id =  models.AutoField(primary_key=True)
        name = models.CharField(max_length=18)
        age = models.IntegerField()
        birth_date = models.DateField()
    

    1. 创建记录的 方式一:

      def orm(request):
      student_obj = models.Student(
      name = 'jiege',
      age = 23,
      birth_date = '1995-01-27'
      )
      student_obj.save()
      return render(request,'myorm.html')

      创建记录的 方式二:

      两种方式
      一种 models.Student.objects.create(name='yuhao',...) # 关键字
      另一种 models.Student.objects.create(**{'name':'liangdao',....}) # 字典打散

      def orm(request):
      new_obj = models.Student.objects.create(name='yuhao',age=25,birth_date='1995-02-06')
      print(new_obj) # Student object -- model对象
      print(new_obj.name) # 点属性,可以获取对应字段的数据
      return render(request,'myorm.html')

       new_obj = models.Student.objects.create(**{'name':'liangdao','age':'25','birth_date':'1994-07-22'})
       print(new_obj)
       print(new_obj.name)
       return render(request,'myorm.html')
      

      创建记录的 方式三:(批量创建,bulk_create)

      def orm(request):
      obj_list = []
      for i in range(5):
      obj = models.Student(
      name=f'xiaobai{i}',
      age=i+1,
      birth_date='2000-01-01'
      )
      obj_list.append(obj)
      models.Student.objects.bulk_create(obj_list)
      return render(request,'myorm.html')

      创建记录的 方式四:(有就更新,没有就创建,update_or_create)

      def orm(request):
      models.Student.objects.update_or_create(
      name='baobao',
      age=23,
      birth_date='1995-03-15'
      )
      return render(request,'myorm.html')

      添加日期的数据,要注意:

      方式一:
      models.Student.objects.create(birth_date='1996-11-15') # 字符串的形式

      方式二:
      import datetime
      now_date = datetime.datetime.now()
      models.Student.objects.create(birth_date=now_date) # 此时插入的仍然是date类型,2019-7-19 这样

    如果想打印orm转换过程中的sql,需要在settings中进行如下配置:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }  
    
    1. 简单的查

      .all方法 查询所有的数据 返回的是queryset集合

      all_objs = models.Student.objects.all()
      print(all_objs)

      <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]> -- 类似于列表 -- queryset集合

      all_objs = models.Student.objects.all()
      for i in all_objs:
      print(i.name)

      jiege、yuhao.....,点属性可以取出对应的数据

      .filter方法 条件查询 返回的也是queryset集合,查询不到内容,不会报错,返回一个<QuerySet []>空的queryset

      objs = models.Student.objects.filter(id=2) # 找id为2的那条记录
      print(objs) # <QuerySet [<Student: Student object>]>

      objs1 = models.Student.objects.filter(name='dazhuang')
      print(objs1) # <QuerySet []> 没找到不报错,显示空

      objs = models.Student.objects.filter(id=2,name='yuhao')

      里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系搞不定

      print(objs) # <QuerySet [<Student: Student object>]>

      .get方法 条件查询 返回的是model对象,而且get方法有且必须只有1个结果

      obj = models.Student.objects.get(id=3) # 找id为3的那条记录
      print(obj) # model对象,Student object
      print(obj.name) # 点属性,可以取出对应的数据,liangdao

    2. delete方法,queryset 和model对象都可以调用

      models.Student.objects.get(id=13).delete() # model对象来调用的delete方法

      models.Student.objects.filter(age=1).delete() # queryset调用的delete方法

      models.Student.objects.all().delete() # 删除所有

    3. update方法,

    只能queryset调用

    model对象不能调用更新方法 报错信息'Student' object has no attribute 'update'

    models.Student.objects.get(name='jiege').update(age=28)
    # .get()返回的是model对象,不能调用update方法,会报错
    
    models.Student.objects.filter(name='jiege').update(age=28)
    # .filter()返回的是queryset对象,可以调用update方法
    

    (二)、查询接口

    • all() 查所有
      查询所有结果,结果是queryset类型

    • filter(**kwargs) 条件查询
      它包含了与所给筛选条件相匹配的对象,结果也是queryset类型
      models.Student.objects.filter(id=2,name='yuhao')
      # 里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系搞不定

      models.Student.objects.filter(**{'id':2,'name':'yuhao'})
      # 打散形式传参
      
    • get(**kwargs) 条件查询
      返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,也就是model对象,返回结果有且只有一个,
      如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。

    • exclude(**kwargs) 排除
      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型

      objects控制器和queryset集合都可以调用exclude,返回结果是queryset类型
      
      # objects控制器调用(objects后直接加exclude方法):
      	query = models.Student.objects.exclude(id=1)
      	print(query) # 找到除了id是1的数据
          
      # queryset集合调用
      	query = models.Student.objects.filter(age=38).exclude(id=6)
      	print(query) # 找到age是38,除了id是6的数据
      
    • order_by(*field) 排序
      queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型

      objs = models.Student.objects.all().order_by('age')
      # 默认是按照升序排列的,也就是按照age的升序排列
      
      objs = models.Student.objects.all().order_by('age','id')
      # 多条件的,逗号隔开,先按照age升序排列,在age相同的情况下,按id升序排列
      
      objs = models.Student.objects.all().order_by('age','-id')
      # 降序排列,加一个'-'就可以
      
    • reverse() 反转
      queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型

      # 用在排序之后反转
      query = models.Student.objects.all().order_by('age').reverse()
      print(query)
      
    • count() 计数
      queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。

      objs = models.Student.objects.all().count()
      print(objs)
      
    • first() 第一条记录
      queryset类型的数据来调用,返回第一条记录,得到的都是model对象,不是queryset

      obj = models.Student.objects.all().first()
      print(obj)
      
    • last() 最后一条记录
      queryset类型的数据来调用,返回最后一条记录,结果为model对象类型

      obj1 = models.Student.objects.all().last()
      print(obj1)
      
    • exists() 判断是否包含查的数据,返回True或False
      queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False

      空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
      
      例:all_books = models.Book.objects.all().exists() 
      # 翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
      
    • values(*field) 用的比较多 返回一个字典序列
      queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。

      obj = models.Student.objects.filter(age=25).values()
      print(obj)
      # <QuerySet [{'id': 2, 'name': 'yuhao', 'age': 25, 'birth_date': datetime.date(1995, 2, 6)}, {'id': 3, 'name': 'liangdao', 'age': 25, 'birth_date': datetime.date(1994, 7, 22)}]>
      
      obj = models.Student.objects.filter(age=25).values('name','age')
      print(obj)
      # <QuerySet [{'id': 2, 'name': 'yuhao', 'age': 25}, {'id': 3, 'name': 'liangdao', 'age': 25 }]>
      
    • values_list(*field) 返回一个元组序列
      它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

      obj = models.Student.objects.filter(age=25).values_list('name','age')
      print(obj)
      # <QuerySet [('yuhao', 25), ('liangdao', 25)]>
      
    • distinct() 去重
      values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录,结果还是queryset

      query = models.Student.objects.all().values('age').distinct()
      print(query)
      

    (三)、基于双下划线的模糊查询

    1. __in=[]  值等于列表里任意一个的对象
    	obj = models.Student.objects.filter(age__in=[22,25,28])
    	print(obj)
        # <QuerySet [<Student: jiege>, <Student: yuhao>, <Student: liangdao>, <Student: zhumo>]>
        
    2. __gt  大于   __gte  大于等于
    	obj = models.Student.objects.filter(age__gt=25)
    	print(obj)
    	# <QuerySet [<Student: jiege>]>
    	# 注意,别写age>25,这种参数不支持
        
    3. __lt  小于   __lte  小于等于
    
    4. __range=[]  值在一个范围内
    	obj = models.Student.objects.filter(age__range=[22,25])
    	print(obj)
        # sql的between and,大于等于22,小于等于25
        
    5. __contains  包含
        obj = models.Student.objects.filter(name__contains='xiao')
        print(obj)
        # name中包含xiao的
        
    6. __icontains 包含,不区分大小写
        obj = models.Student.objects.filter(name__contains='xiao')
        print(obj)
        # name中包含xiao的,不区分大小写,比如Xiao这种也能识别出来
        
    7.  __startswith  以什么开头   __endswith  以什么结尾
    
    8. __year  找日期年份相关的   __month 月份
        obj = models.Student.objects.filter(birth_date__year='1995')
        print(obj)
        # 找生日是1995年的人
        
        obj1 = models.Student.objects.filter(birth_date__year='1995',birth_date__month='01')
        print(obj1)
        # 找生日是1995年1月份的人
    

    .

  • 相关阅读:
    poj1466
    vc剪贴板
    【转帖】BCGControlBar使用心得如何捕获Workspace bar类上的树控件的消息
    Windows API一日一练
    BCG 使用CBCGPToolbarFontSizeCombo 时下拉框无内容
    VB API教程 王国荣
    用API 现成的函数处理工程退出时的文件保存
    VC 剪贴板操作
    BCG中使用状态栏显示状态信息
    界面库
  • 原文地址:https://www.cnblogs.com/yangzm/p/11221109.html
Copyright © 2011-2022 走看看