博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

django中的queryset对象和object对象

1.queryset是查询集,就是传到服务器上的url里面的内容。django会对查询返回的结果集queryset进行缓存,这里是为了提高查询效率。
也就是说,在你创建一个queryset对象的时候,django并不会立即向数据库发出查询命令,只有在你需要用到这个queryset的时候才会去数据库查询。
2.objects是django实现的mvc框架中的数据层(model)m,django中的模型类都有一个objects对象,它是一个django中定义的queryset类型的对象,
它包含了模型对象的实例。简单的说,objects是单个对象,queryset是许多对象。
queryset可以被构造,过滤,切片,作为参数传递,这些行为都不会对数据库进行操作。只要你查询的时候才真正的操作数据库。

django测试环境搭建

1.pycharm连接数据库都需要提前下载对应的驱动
2.自带的sqlite3对日期格式数据不敏感
# 方式1:任意创建一个py文件,在该文件内书写固定的配置
import os
if __name__ == "__main__":
   os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dj0302.settings")
   import django
   django.setup()
# 方式2:直接使用pycharm提供的python console

单表查询关键字

QuerySet对象常用方法
query  # 查看orm内部对应的SQL语句

# 增
   # res=models.Books.objects.create(title='三国演义',price=944.28)
   # print(res.title)
   '''create返回值就是当前被创建的数据对象'''
   # 查
   # res=models.Books.objects.all()
   # print(res.query)
   # res=models.Books.objects.filter()
   # print(res.query)
   # res=models.Books.objects.filter(title='ldb')
   # print(res)
   '''filter括号内可以放多个参数 默认是and关系 推荐使用 条件不符合不会报错'''
   # res=models.Books.objects.get(title='ldb')
   # print(res)
   '''get括号内可以放多个参数 默认是and关系 不推荐使用 条件不符合直接报错'''
   # 改
   # res=models.Books.objects.filter(pk=1).update(price=666.66)
   # print(res) # 返回值是受影响的行数

   # book_obj=models.Books.objects.filter(pk=5).first()
   # book_obj.price=500.55
   # book_obj.save() # 效率低(所有字段重新写一遍)
   '''pk能够自动查找到当前表的主键字段 不需要查看当前表主键字段名'''
   # 删
   # models.Books.objects.filter(pk=1).delete()

   # 1.first() 取第一个数据对象
   # res=models.Books.objects.all().first()
   # res1=models.Books.objects.all()[0]
   # res2=models.Books.objects.all()[0:2]
   # print(res,res1,res2)
   '''queryset对象还支持切片操作 但是只能填正数'''
   # 2.last() 取最后一个数据对象
   # res=models.Books.objects.all().last()
   # print(res)
   # 3.values() 获取数据指定字段的值
   # res=models.Books.objects.all().values('title','publish_time')
   # res1=models.Books.objects.values('title','publish_time')
   # print(res,res1)
   '''all()加不加都表示所有数据 values获取的结果 类似于列表套字典'''
   # 4.values_list() 获取数据指定字段的值
   # res=models.Books.objects.values_list('title','publish_time')
   # print(res)
   '''values_list获取的结果 类似于列表套元组'''
   # 5.order_by() 排序
   # res=models.Books.objects.order_by('price') # 默认是升序
   # print(res)
   # res=models.Books.objects.order_by('-price') # 减号降序
   # print(res)
   # 6.count() 计数
   # res=models.Books.objects.count() # 统计数据条数
   # print(res)
   # 7.distinct() 去重
   # res=models.Books.objects.values('title').distinct()
   # print(res)
   # 8.exclude() 排除什么在外 取反操作
   # res=models.Books.objects.exclude(title='三国演义')
   # print(res.query)
   # 9.reverse() 反转
   # res=models.Books.objects.order_by('price').reverse()
   # print(res)
   '''reverse需要先排序之后才能反转'''
   # 10.exists() 判断是否有数据 返回布尔值
   # res=models.Books.objects.exists()
   # print(res)

神奇的双下划线查询(范围查询)

# 1.查询价格大于700的书籍
   # res=models.Books.objects.filter(price__gt=700)
   # print(res)
   # print(res.query)
   # 2.查询价格小于700的书籍
   # res=models.Books.objects.filter(price__lt=700)
   # print(res)
   # 3.查询书名是红楼梦,三国演义的书籍
   # res=models.Books.objects.filter(title__in=['红楼梦','三国演义'])
   # print(res)
   # 4.查询价格在600到700之间
   # res=models.Books.objects.filter(price__range=(500,800))
   # print(res)
   # 5.查询书名中包含字母s的书
   # res=models.Books.objects.filter(title__contains='s') # 区分大小写
   # print(res)
   # res=models.Books.objects.filter(title__icontains='s') # 不区分大小写
   # print(res)
   # 6.查询出版日期是2021的书
   # res=models.Books.objects.filter(publish_time__year=2021)
   # print(res)
   # 7.查询出版日期是3月的书
   # res=models.Books.objects.filter(publish_time__month=3)
   # print(res)

图书管理系统表设计

'''
auto_now
修改数据会自动修改为当前时间
auto_now_add
是创建数据的时间 修改数据不会自动修改时间
'''
class Book(models.Model):
   title=models.CharField(verbose_name='书名',max_length=32)
   price=models.DecimalField(verbose_name='价格',max_digits=8,decimal_places=2)
   publish_time=models.DateField(verbose_name='出版日期',auto_now_add=True)
   # 书籍和出版社是一对多关系 外键字段建在多的一方
   publish=models.ForeignKey(to='Publish')
   # 书籍和作者是多对多关系 外键字段建在查询频率较高的表中
   authors=models.ManyToManyField(to='Author')

class Publish(models.Model):
   title=models.CharField(verbose_name='出版社名称',max_length=32)
   addr=models.CharField(verbose_name='出版社地址',max_length=128)
   email=models.EmailField(verbose_name='邮箱')

class Author(models.Model):
   name=models.CharField(verbose_name='姓名',max_length=32)
   age=models.IntegerField(verbose_name='年龄')
   # 作者和作者详情是一对一的关系 外键字段建在查询频率较高的表中
   author_detail=models.OneToOneField(to='AuthorDetail')

class AuthorDetail(models.Model):
   phone=models.BigIntegerField(verbose_name='电话')
   addr=models.CharField(verbose_name='地址',max_length=32)
'''
作者详情表
作者表
出版社表

书籍表和关系表通过orm实现
'''

外键字段操作

# 直接传主键值
   # models.Book.objects.create(title='蛙',price=98.55,publish_id=1)
   # 传数据对象
   # publish_obj=models.Publish.objects.filter(pk=1).first()
   # models.Book.objects.create(title='追风筝的人',price=65.25,publish=publish_obj)
   # 修改数据
   # models.Book.objects.filter(pk=1).update(publish_id=2)
   # publish_obj=models.Publish.objects.filter(pk=3).first()
   # models.Book.objects.filter(pk=2).update(publish=publish_obj)
   '''多对多外键字段'''
   # 增
   # book_obj=models.Book.objects.filter(pk=3).first()
   # 主键值
   # book_obj.authors.add(5)
   # 作者对象
   # author_obj=models.Author.objects.filter(pk=6).first()
   # book_obj.authors.add(author_obj)
   # 括号内支持传多个参数
   # book_obj.authors.add(6,7)
   # author_obj1=models.Author.objects.filter(pk=5).first()
   # author_obj2=models.Author.objects.filter(pk=7).first()
   # book_obj.authors.add(author_obj1,author_obj2)
   # 改
   # book_obj=models.Book.objects.filter(pk=2).first()
   '''整形不能被迭代 列表、元组等容器类型才能被迭代'''
   # book_obj.authors.set([7,]) # 列表
   # book_obj.authors.set((5,6)) # 元组
   # book_obj.authors.set([author_obj1, ])
   # book_obj.authors.set([author_obj1, author_obj2])
   # 删
   # book_obj.authors.remove(6)
   # book_obj.authors.remove(5,6)
   # book_obj.authors.remove(author_obj1,author_obj23)
   # 清空
   # book_obj.authors.clear() # 去第三张关系表中删除所有跟书籍对应的记录
   '''
  add()
  remove()
  括号内既可以传数字也可以传对象 逗号隔开即可
  set()
  括号内必须传可迭代对象 可迭代对象内既可以传数字也可以传对象 支持多个
  clear()
  清空操作 无需传值
  '''

跨表查询理论

正向
从有外键字段的表查与其有关联的表就是正向
反向
与正向查询相反,从没有外键字段的表查
# 就是判断你是否有关联的外键字段
'''
正向查询按外键字段
反向查询按表名小写加_set
'''

基于对象的跨表查询

# 连表操作(子查询)
'''
1.先查询出一个对象
2.基于对象点正反向字段
'''

反向查询表名小写加_set
查询的对象可能有多个情况
查询的对象只有一个的情况不需要加
#########################################################################
# 基于对象的跨表查询
'''正向查询'''
   # 1.查询三国演义对应的出版社名称
   # book_obj=models.Book.objects.filter(title='三国演义').first()
   # res=book_obj.publish
   # print(res)
   # 2.查询蛙人对应的作者
   # book_obj=models.Book.objects.filter(title='蛙').first()
   # res=book_obj.authors.all()
   # print(res)
   # 3.查询ldb的地址
   # author_obj=models.Author.objects.filter(name='ldb').first()
   # res=author_obj.author_detail
   # print(res.addr,res.phone)
   '''反向查询'''
   # 4.查询东方出版社出版过的书籍
   # publish_obj=models.Publish.objects.filter(title='东方出版社').first()
   # res=publish_obj.book_set.all()
   # print(res)
   # 5.查询ldb写过的书
   # author_obj=models.Author.objects.filter(name='ldb').first()
   # res=author_obj.book_set.all()
   # print(res)
   '''反向查询一对一情况不需要加_set'''
   # 6.查询电话是2121515的作者姓名
   # author_detail_obj=models.AuthorDetail.objects.filter(phone=2121515).first()
   # res=author_detail_obj.author
   # print(res.name,res.age)
'''
总结
正向查询对象.外键
反向查询对象.表名小写加_set
'''

基于双下划线的跨表查询

# 连表操作(inner join)
######################################################################
# 基于双下划线查询
# 1.查询三国演义对应的出版社名称
   # res=models.Book.objects.filter(title='三国演义').values('publish__title')
   # print(res.query)
   # 2.查询蛙对应的作者名字和年龄
   # res=models.Book.objects.filter(title='蛙').values('authors__name','authors__age')
   # print(res)
   # 3.查询ldb的地址
   # res=models.Author.objects.filter(name='ldb').values('author_detail__addr')
   # print(res)

   # 1.查询三国演义对应的出版社名称
   # res=models.Publish.objects.filter(book__title='三国演义').values('title')
   # print(res.query)
   # 2.查询蛙对应的作者名字和年龄
   # res=models.Author.objects.filter(book__title='蛙').values('name','age')
   # print(res)
   # 3.查询ldb的地址
   # res=models.AuthorDetail.objects.filter(author__name='ldb').values('addr')
   # print(res)

   # 查询三国演义对应的作者的电话和地址
   # res=models.Book.objects.filter(title='三国演义').values('authors__author_detail__phone','authors__author_detail__addr')
   # print(res)