zoukankan      html  css  js  c++  java
  • Django 05

    配置测试脚本文件

    • 直接在app下面的 test.py 中进行如下配置
    • 注意: 必须完成如下配置之后才能导入我们需要测试的文件
    from django.test import TestCase
    # 1.从manage.py copy 这几行代码
    import os
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings")
        # 2.自己写两行
        import django
        django.setup()
        
        # 3.把上面的环境搭好才能导入我们需要测试的模块
    
    
    • 查看内部具体的SQL语句可以将下面的代码copy到settings.py文件的最下方
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level': 'DEBUG',
            },
        }
    }
    

    单表操作

    增加数据

    增加数据的两种方法

    • 通过QuerySet对象的create方法创建
    • 通过对象的save方法创建
    # 1.QuerySet对象的create方法
    book_obj = models.Books.objects.create(title='三国演义', price=66.66, publish_date='2019-1-1')
    
    # 2.对象的save方法
    book_obj = models.Books(title='西游记', price=77.77, publish_date='2018-1-1')
    book_obj.save()
    

    查询数据

    同样的, 查询数据也有两种方法

    • 通过QuerySet对象的filter方法查询---> 返回的是一个QuerySet对象

    • 通过QuerySet对象的get方法查询---> 返回的就是数据对象

    • 注意: 1. 使用get方法当条件不存在时会报错
      2.orm语句的查询都是惰性查询, 当你使用数据的时候才会执行
      3.只要是QuerySet对象就可以无限制的使用QuerySet的方

             ​          4.只要是QuerySet对象就可以使用 `.query` 的方法 查看当前结果对应的sql语句
      
    # 1.filter
    res = models.Books.objects.filter(pk=1).first()
    # 查看当前结果对应的sql语句
    print(res.query)
    '''
    SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1
    '''
    
    # 2.get
    # 查询条件不存在会报错
    res = models.Books.objects.get(pk=4)
    print(res)
    '''
    app01.models.DoesNotExist: Books matching query does not exist.
    '''
    

    修改数据

    • QuerySet的update的方法
    • 对象.属性进行修改, 然后save方法保存
      • 不推荐使用, 效率低
    # 1.QuerySet的update方法
    models.Books.objects.filter(pk=1).update(price=88.88)
    
    # 2.对象的save()方法
    book_obj = models.Books.objects.filter(pk=1).first()
    book_obj.price = 66.66
    book_obj.save()
    

    删除数据

    • QuerySet的delete方法
    • 对象的delete方法
    # 删除数据的两种方法
    # 1.query set方法
    models.Books.objects.filter(pk=1).delete()
    
    # 2.对象方法
    book_obj = models.Books.objects.filter(pk=2)
    book_obj.delete()
    

    查询十三太保

    +----+----------+-------+--------------+
    | id | title    | price | publish_date |
    +----+----------+-------+--------------+
    |  1 | 三国演义 | 66.66 | 2019-01-01   |
    |  2 | 西游记   | 77.77 | 2018-01-01   |
    |  3 | 水浒传   | 88.88 | 2017-01-01   |
    |  4 | 红楼梦   | 99.99 | 2016-01-01   |
    |  5 | 三国演义 | 66.66 | 2016-01-01   |
    +----+----------+-------+--------------+
    
    
    
    # 1.all 查询所有, 返回QuerySet对象
    res = models.Books.objects.all()
    
    # 2.filter 筛选, 返回QuerySet对象
    res = models.Books.objects.filter(pk=1, price=66.66)
    
    # 3.get 获取的数据对象本身, 条件不存在会报错, 并且条件必须是唯一的, 不然也报错
    res = models.Books.objects.get(title='三国演义')
    
    
    # 4.first() 获取QuerySet中的第一个数据对象
    res = models.Books.objects.filter().first()
    
    
    # 5.last() 获取QuerySet中最后一个数据对象
    res = models.Books.objects.all().last()
    
    
    # 6.count() 统计数据对象的个数
    num = models.Books.objects.count()
    print(num)  # 4
    
    # 7.values() 获取指定的字段数据, 返回的是一个queryset对象, 列表套字典
    res = models.Books.objects.values('title', 'price')
    print(res)
    
    '''
    <QuerySet [{'title': '三国演义', 'price': Decimal('66.66')}, {'title': '西游记', 'price': Decimal('77.77')}, {'title': '水浒传', 'price': Decimal('88.88')}, {'title': '红楼梦', 'price': Decimal('99.99')}]>
    '''
    
    
    # 8.values_list() 获取指定的字段数据, 返回的是一个queryset对象, 列表套元祖
    res = models.Books.objects.values_list('title', 'price')
    print(res)
    
    '''
    <QuerySet [('三国演义', Decimal('66.66')), ('西游记', Decimal('77.77')), ('水浒传', Decimal('88.88')), ('红楼梦', Decimal('99.99'))]>
    '''
    
    
    # 9.order_by() 按照字段排序, 返回的是一个QuerySet对象
    res1 = models.Books.objects.order_by('price')  # 默认是升序
    res2 = models.Books.objects.order_by('-price')  # 降序
    # res = models.Books.objects.all().order_by('price')  
    
    
    # 10.reverse() 颠倒顺序, 和order_by联用, 返回的是一个QuerySet对象
    res = models.Books.objects.all().order_by('price').reverse()
    
    
    # 11.exclude() 排除, 返回的是一个QuerySet对象
    res = models.Books.objects.all().exclude(title='三国演义')
    
    
    # 12.exist() 判断查询结果是否有值, 返回一个布尔值
    res = models.Books.objects.filter(pk=1).exists()
    print(res)
        
    # 13.distinct() 去重, 前提是数据必须是完全相同的情况下, 容易忽略主键
    # 主键不同, 因此即使其他字段的值完全一样, 还是会把两个都查询出来
    res1 = models.Books.objects.filter(title='三国演义').distinct()
    res2 = models.Books.objects.values('title').distinct()
    print(res1)  # <QuerySet [<Books: Books object>, <Books: Books object>]>
    print(res2)  # <QuerySet [{'title': '三国演义'}, {'title': '西游记'}, {'title': '水浒传'}, {'title': '红楼梦'}]>
    

    双下划线查询

    +----+----------------+-------+--------------+
    | id | title          | price | publish_date |
    +----+----------------+-------+--------------+
    |  1 | 三国演义       | 66.66 | 2019-01-01   |
    |  2 | 西游记         | 77.77 | 2018-01-01   |
    |  3 | 水浒传         | 88.88 | 2017-01-01   |
    |  4 | 红楼梦         | 99.99 | 2016-01-01   |
    |  5 | 三国演义       | 66.66 | 2016-01-01   |
    |  6 | Three kingdoms | 55.55 | 2015-01-01   |
    |  7 | Three Kingdoms | 44.44 | 2014-01-01   | Kingdoms 的 King 是大写
    +----+----------------+-------+--------------+
    
    # 1.__gt 大于
    res = models.Books.objects.filter(price__gt=80)
    print(res)
    
    # 2.__lt 小于
    res = models.Books.objects.filter(price__lt=80)
    print(res)
    
    # 3.__gte 大于等于
    res = models.Books.objects.filter(price__gte=88.88)
    print(res)
    
    # 4.__lte 小于等于
    res = models.Books.objects.filter(price__lte=77.77)
    print(res)
    
    # 5.__in 或者
    res = models.Books.objects.filter(price__in=[88.88, 99.99]) 
    print(res)  # 查询结果为空, 是因为我们的价格都是小数, python小数精度很低
    
    # 6.__range 范围(顾头顾尾) 相当于  <= x <=
    res = models.Books.objects.filter(price__range=(70, 90))
    print(res)
    
    # 7.__year 
    res = models.Books.objects.filter(publish_date__year='2019')
    print(res)
    
    # 8.__month 月份
    res = models.Books.objects.filter(publish_date__month='1')
    print(res)
    
    
    
    """
        MySQL 中的模糊查询
        关键字: like
        符号:
            % 匹配任意个数字符
            _ 匹配一个字符
    """
    
    # 9.__startswith 以...开头
    res = models.Books.objects.filter(title__startswith='三国')
    print(res)
    
    # 10.__endswith 以...结尾
    res = models.Books.objects.filter(title__endswith='梦')
    print(res)
    
    # 11.__contains 包含... (区分大小写)
    res = models.Books.objects.filter(title__contains='king')
    print(res)  # <QuerySet [<Books: Books object>]>
    
    # 12.__icontains 包含...(不区分大小写)
    res = models.Books.objects.filter(title__icontains='king')
    print(res)  # <QuerySet [<Books: Books object>, <Books: Books object>]>
    
    

    连表下的数据增删改

    • 比如我们现在新建的book表, 表中的存在publish_id外键字段, 我们在表中创建数据时, 该如何给这个字段传值呢?

    一对多/一对一

    # 一对多
    # 增加数据
    # 1.实际字段, 传外键的id值
    models.Book.objects.create(title='三国演义', price='66.66', publish_date='2019-1-1', publish_id=1)
    
    # 2.虚拟字段, 直接传对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='西游记', price='77.77', publish_date='2018-1-1', publish=publish_obj)
    
    
    # 修改数据
    # 1.实际字段, 传外键id值
    models.Book.objects.filter(pk=1).update(publish_id=2)
    
    # 2.虚拟字段, 直接传对象
    models.Book.objects.filter(pk=2).update(publish=publish_obj)
    
    
    # 删除数据 (默认是级联更新)
    models.Publish.objects.filter(pk=1).delete() # 会删除关联表内相应的行
    

    多对多

    • 多对多关系表的数据操作
    # add增加多对多关系表数据的两种方法
    
    """
        add方法用于向多对多关系表中添加数据
        支持  对象(包含虚拟外键字段)(1, 2)  --> 1, 2 代表的还是关联表的id值
        也支持 对象(包含虚拟外键字段)(author_obj1, author_obj2)
         authors是建立多对多外键时的虚拟字段, book_obj.authors可以理解为进入了多对多关系表中
    """
    
    # 先筛选出一个书籍对象
    book_obj = models.Book.objects.filter(pk=2).first()
    
    # 1.添加id值
    book_obj.authors.add(2)
    book_obj.authors.add(3, 4)  # add方法也支持多个参数
    
    # 2.添加对象
    author_obj1 = models.Book.objects.first(pk=2).first()
    author_obj2 = models.Book.objects.first(pk=3).first()
    
    book_obj.authors.add(author_obj1, author_obj2)
    
    
    
    # set方法修改多对多关系表中的数据
    
    """
        set方法用于修改多对多关系表中的数据
        既可传id值, 也可以传对象, 注意!!!必须是可迭代对象!!!
        支持多个
    
    """
    
    book_obj = models.Book.objects.filter(pk=4).first()
    # 1.添加一个可迭代对象, 里面包含id值
    book_obj.authors.set((3, 4))
    # 2.添加一个可迭代对象, 里面包含对象
    book_obj.authors.set((author_obj1, author_obj2))
    
    
    
    # remove方法删除多对多关系表数据
    
    """
        remove即可以传id值, 也可以传对象,
        并且支持多个, 不需要是可迭代对象
    """
    
    book_obj = models.Book.objects.filter(pk=2).first()
    # 1.添加id值
    book_obj.authors.remove(3, 4)
    # 2.添加对象
    book_obj.authors.remove(author_obj1, author_obj2)
    
    
    
    # clear方法可以清空多对多关系表中某个对象的全部数据
    
    """
        clear 清空对象的所有数据
    """
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.clear()
    

    跨表查询

    • 关系字段在A表上, 由A表查B表是 正向查询, 由B表查A表是 反向查询

    基本对象的跨表查询 (子查询)

    • 正向查询用: 对象.虚拟字段--->得到对象 (多个结果要 .all() )
    • 反向查询用类名小写: 对象.类名(小写)--->得到对象 (多个结果需要 _set.all() )
    # 1.查询书籍主键为2的出版社名称
    book_obj = models.Book.objects.filter(pk=2).first()
    print(book_obj.publish)  # 虚拟字段, 拿到的出版社对象
    print(book_obj.publish.name)
    
    # 2.查询书籍主键的为3的作者姓名
    book_obj = models.Book.objects.filter(pk=4).first()
    print(book_obj.authors.all())  # 多个作者对象
    
    """
        当我们反向查询的结果可能有多个时, 需要加_set.all()
    """
    
    # 3.查询出版社的是东方出版社出版的书
    publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    print(publish_obj.book_set.all())
    
    # 5.查询作者是alpha写过的书籍
    author_obj = models.Author.objects.filter(name='alpha').first()
    print(author_obj.book_set.all())
    
    # 6.查询手机号是111的作者姓名
    author_detail_obj = models.AuthorDetail.objects.filter(phone='111').first()
    print(author_detail_obj.author.name)
    

    基于双下划线的跨表查询 (连表查询)

    # 1.查询书籍pk为2的出版社名称
    # 正向
    res = models.Book.objects.filter(pk=2).values('publish__name')
    print(res)
    # 反向
    models.Publish.objects.filter(book__pk=2).values('name')
    print(res)
    
    # 2.查询书籍pk为2的作者姓名和邮箱
    # 正向
    res = models.Book.objects.filter(pk=2).values('authors__name', 'authors__email')
    print(res)
    # 反向
    res = models.Author.objects.filter(book__pk=2).values('name', 'email')
    print(res)
    
    # 3.查询作者是bravo的家庭地址
    # 正向
    res = models.Author.objects.filter(name='bravo').values('author_detail__addr')
    print(res)
    # 反向
    res = models.AuthorDetail.objects.filter(author__name='bravo').values('addr')
    print(res)
    
    # 查询书籍为pk是2的作者的手机号
    # 正向
    res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
    print(res)
    # 反向
    res = models.Author.objects.filter(book__pk=2).values('author_detail__phone')
    print(res)
    
  • 相关阅读:
    【Java学习系列】第3课--Java 高级教程
    【夯实PHP基础】nginx php-fpm 输出php错误日志
    【夯实Mysql基础】MySQL性能优化的21个最佳实践 和 mysql使用索引
    【架构设计】分布式文件系统 FastDFS的原理和安装使用
    【13】2016.12.13 周二--《小结2016》
    【诗词歌赋】2016.12.15 周四--文言鸿儒《年终的日常》
    【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
    【夯实Nginx基础】Nginx工作原理和优化、漏洞
    【夯实PHP基础】PHP的反射机制
    HTML DOM简易学习笔记
  • 原文地址:https://www.cnblogs.com/bigb/p/11946547.html
Copyright © 2011-2022 走看看