zoukankan      html  css  js  c++  java
  • 5.ORM模型层--单表查询

    ORM模型层--单表查询

    1.ORM模型层

    ​ ORM是“对象-关系-映射”的简称,orm其实就是将类对象的语法翻译成sql语句的一个引擎

    特点:

    ​ orm开发效率高 执行效率低

    ​ orm迁移数据库方便: 从Mysql -- 迁移到oracle 不需要重写建表语句

    数据库迁移(同步)指令

    # python manage.py makemigrations
    # python manage.py migrate
    

    2.单表查询

    创建表

    在应用的models.py文件中声明类

    from django.db import models
    
    # 表名 -- app01_book  应用_小写表名
    class Book(models.Model):
        # id = models.AutoField(primary_key=True)
        # id int primary key auto_increment
        # 生成表时,会自动生成一个id主键字段
    
        title = models.CharField(max_length=32)
        # title varchar(32) not null 自动有一个约束不能为空
    
        price = models.IntegerField()
        # price int not null
    
        pub_date = models.DateField()
        # pub_date date not null
    
        publish = models.CharField(max_length=32)
        
        def __str__(self): 
            return self.title #查询书籍对象时会返回书籍名称
    

    执行数据库迁移(同步)指令

     python manage.py makemigrations
     python manage.py migrate
    

    配置连接mysql

    第一步: 去mysql中创建库

    mysql> create database orm01 charset=utf8mb4;  # utf8mb4支持中文  utf8有些生僻字它不支持
    

    第二步:

    settings.py文件中进行如下修改

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'orm01',    #要连接mysql数据库名称
            'HOST': '127.0.0.1', #连接地址--本地连接
            'PORT': '3306',     #端口号3306
            'USER':  'root',   #用什么用户连接
            'PASSWORD': '123456' #数据库密码
        }
    }
    

    第三步:

    在项目主目录下面的__init__.py文件中指定连接mysql数据的客户端模块

    import pymysql
    pymysql.install_as_MySQLdb()
    

    第四步:

    执行数据库迁移(同步)指令

     python manage.py makemigrations
     python manage.py migrate
    

    字段参数介绍

    (1)null
     
    如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
     
    (1)blank
     
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
     
    (2)default
     
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
     
    (3)primary_key
     
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
     
    (4)unique
     
    如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
     
    (5)db_index 
      如果db_index=True 则代表着为此字段设置数据库普通索引。    
    
    (6)choices
    由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
    
    DatetimeField(日期时间)、DateField(日期)、TimeField(时间)这个三个时间字段,都可以设置如下属性。
    (7)auto_now_add
        配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    
    (8)auto_now
        配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
    

    13个查询接口(必知必会)

    <1> all(): objects控制器或者queryset类型数据调用,查询所有结果,结果是queryset类型
      
    <2> filter(**kwargs): objects控制器或者queryset类型数据调用,它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
      
    <3> get(**kwargs): objects控制器或者queryset类型数据调用,返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。  Book.objects.get(id=1)
        两个报错:
          查询结果多于1个了: get() returned more than one Book -- it returned 2!
          查询结果没有: Book matching query does not exist.
        
    <4> exclude(**kwargs): 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
                     
    <5> order_by(*field): queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
      models.Book.objects.all().order_by('price','id') 
    #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
            
    <6> reverse(): queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
    	但是:只对排序之后的数据才能进行翻转:
        all_books = models.Book.objects.all().order_by('id').reverse()
           
    <7> count(): queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
      	all_books = models.Book.objects.all().count()  # 14
      
    <8> first(): queryset类型的数据来调用,返回第一条记录 
        Book.objects.all()[0] = Book.objects.all().first(),得到的都是model对象,不是queryset类型
      
    <9> last(): queryset类型的数据来调用,返回最后一条记录
      
    <10> exists(): queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False.
        queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exists
     例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
     
    <11> values(*field): 用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
        # all_books = models.Book.objects.values('title', 'price')
        all_books = models.Book.objects.all().values('title', 'price')
    得到结果:# <QuerySet [{'title': '白金鸽3', 'price': 12}, {'title': '王照', 'price': 3}, ....
        
    <12> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values()返回的是一个字典序列
     	# all_books = models.Book.objects.values_list('title', 'price')
        all_books = models.Book.objects.all().values_list('title', 'price')
    得到结果:#<QuerySet [('斗破苍穹', 220), ('赘婿', 22),...]>
        
    <13> distinct():去重,配合values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录.
      不使用values和values_list得到的queryset类型的数据里面是模型类对象,id不同,都是不重复的
      all_books = models.Book.objects.values_list('title',).distinct()
    

    基于双下划线的模糊查询

    1.Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
    2.Book.objects.filter(price__gt=100)  #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
    3.Book.objects.filter(price__lt=100) #小于,小于等于是lte=100
    	示例:
        # books = models.Book.objects.filter(price__in=[3,4,5])
        
    4.Book.objects.filter(price__range=[100,200])  #sql的between and,大于等于100,小于等于200
    	示例:
    	#books = models.Book.objects.filter(price__range=[3, 9]) 
    	
    5.Book.objects.filter(title__contains="python")  #title值中包含python的
    6.Book.objects.filter(title__icontains="python") #不区分大小写
    7.Book.objects.filter(title__startswith="py") #以什么开头,istartswith 不区分大小写
    8.Book.objects.filter(title__endswith="on") #以什么开头,iendswith 不区分大小写
    	示例:
        # books = models.Book.objects.filter(title__contains='py') #包含,区分大小写
       
    9.Book.objects.filter(pub_date__year=2012) #month月份,day日期
    	示例:
        # books = models.Book.objects.filter(pub_date__year='2021') # 年份等于2021年的
        # books = models.Book.objects.filter(pub_date__year__gt='2018') # 年份大于2018年的书籍
        books = models.Book.objects.filter(pub_date__year='2021', pub_date__month='2') # 查询2021年2月份的所有书籍
        # books = models.Book.objects.filter(pub_date__year='2021', pub_date__month='2', pub_date__day='3') # 查询2021年2月3日的所有书籍
        books = models.Book.objects.filter(pub_date='2021-2-3') # 查询2021年2月3日的所有书籍
    

    表数据的增删改查

    在应用的views.py视图中声明函数,urls.py路由指向视图函数

    1.增加
    from django.shortcuts import render,HttpResponse
    
    from app01 import models  #想操作表先引入models类
    import datetime
    
    #表数据的增删改查
    def query(request):
    #增加
    #添加数据方式1:
        book_obj = models.Book.objects.create( #objects是Book类的控制器
            title='斗破苍穹',
            price=220,
            # pub_date='2018-05-15', #日期类型数据两种方式:1.字符串
            pub_date=datetime.datetime.now(),#日期类型数据两种方式: 2.日期类型数据
            publish='py33出版社',
        )
        print(book_obj) # Book object 模型类对象,一个模型类对象表示一条记录
    
    #添加数据方式2:
        new_obj = models.Book( #实例化类对象
            title='赘婿',
            price=45,
            pub_date='2020-1-12',
            publish='北京出版社',
        )
        new_obj.save() #创建记录,创建一条数据
        
    #批量增加 一次增加多条记录 效率更高
        obj_list = []
        for i in range(1,10):
            obj = models.Book(
                title=f'赘婿{i}',
                price=45+i*3,
                pub_date=f'2020-10-1{i}',
                publish='北京出版社',
            )
            obj_list.append(obj)
    
        models.Book.objects.bulk_create(obj_list) #批量创建
    
    	return HttpResponse('ok')
    
    2.简单查询
    all() 方法:查询所有记录(查询所有数据的模型类对象),得到的是QuerySet类型数据
        obj_list = models.Book.objects.all()
        print(obj_list)  #QuerySet 类似于列表 里面放的是book模型类对象
        # <QuerySet [<Book: 书名: 表净额>, ...]>
    # 通过模型类对象获取具体数据
        for i in obj_list:
            print(i.title)  #获取书名
            print(i.price)  #获取价钱
            print(i.publish) #获取出版社
            
    filter() 方法:过滤查询,得到的是QuerySet类型数据
        res = models.Book.objects.filter(title='赘婿')
        #得到书名为赘婿的QuerySet类型数据 : <QuerySet [<Book: 书名: 赘婿>]>
        print(res)
    # 获取模型类对象
        print(res[0]) # 支持索引切片,不支持负数形式的索引
        print(res[0].price) #获取书的价格
    
    get() 方法: 根据已知条件进行过滤查询,但是查询结果有且只能有一条,得到的结果是模型类对象
        obj = models.Book.objects.get(title='赘婿')
        print(obj) #模型类对象
        print(obj.price) #书的价格
    
    3.修改
    方式1:update根据Queryset类型数据进行更新,可能批量更新
        models.Book.objects.filter(
            title='赘婿'
       ).update( #更新,但是update只能是Queryset类型的数据来进行调用
            price = 22,
            publish = '好人出版社',
        )
        
    方式2:根据模型类对象进行更新,必须执行save()才能保存更新
        obj = models.Book.objects.get(id=1) #拿到模型类对象
        obj.title = '飞人'
        obj.price = 66
        obj.save() #保存更新
    
    4.删除
    delete() 方法:
        #queryset类型的删除,可能是多条数据
        models.Book.objects.filter(title='斗破哦').delete()
        #模型类对象删除,只能是一条数据
        models.Book.objects.get(title='飞人').delete()
    

    在模型类中新增两个字段

    auto_now_add和auto_now的问题

    from django.db import models
    class Book(models.Model):
    
        title = models.CharField(max_length=32)
        # title varchar(32) unique
    
        d1 = models.DateField(auto_now_add=True)
        d2 = models.DateTimeField(auto_now=True)
    
        def __str__(self):
            return '书名为: '+self.title
    

    执行数据库同步指令时,提示:

    You are trying to add the field 'd1' with 'auto_now_add=True' to book without a default; the database needs something to populate existing rows.
    
     1) Provide a one-off default now (will be set on all existing rows)
     2) Quit, and let me add a default in models.py
    
    解决办法: 字段添加默认是或者设置可以为空
    d1 = models.DateField(auto_now_add=True,null=True,blank=True)
    d2 = models.DateTimeField(auto_now=True,default=1)
    
    注意:自动添加时间时,django默认是用的utc时间,改为本地时间的设置如下
    settings.py文件中改如下配置
    TIME_ZONE = 'UTC'
    #TIME_ZONE = 'Asia/Shanghai'
    
    USE_I18N = True
    USE_L10N = True
    
    # USE_TZ = True  #使用TIME_ZONE时间
    USE_TZ = False   # 使用本地时区
    
    auth_now参数如果使用update方法进行数据更新,那么它不会自动更新时间,失效了
    想让它生效只能通过save方法更新才会生效,所以,我们一般更新记录时间,都是手动通过datetime模块进行更新
    
    
  • 相关阅读:
    hdu 4521 小明系列问题——小明序列(线段树 or DP)
    hdu 1115 Lifting the Stone
    hdu 5476 Explore Track of Point(2015上海网络赛)
    Codeforces 527C Glass Carving
    hdu 4414 Finding crosses
    LA 5135 Mining Your Own Business
    uva 11324 The Largest Clique
    hdu 4288 Coder
    PowerShell随笔3 ---别名
    PowerShell随笔2---初始命令
  • 原文地址:https://www.cnblogs.com/jia-shu/p/14589776.html
Copyright © 2011-2022 走看看