六、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月份的人

.

posted on 2019-07-21 14:24  雨后清明  阅读(210)  评论(0编辑  收藏  举报

导航