Django基础之模型层(02)

 

 

 

1 重要概念

# 多表查询
    """
    正向查询
        
    反向查询
    
    当前查询对象是否含有外键字段
        如果有就是正向
        没有无则是反向
    口诀:
        正向查询按外键字段
            多对多需要额外再加一个.all()
            一对多和一对一不需要加
        反向查询按表名小写
            一对多与多对多
                _set.all()
            一对一
                不需要加
    """

 

2 多表查询

#####################基于对象的跨表查询#####################
    # 子查询:将一张表的查询结果当做另外一条SQL语句的条件(括号括起来)
    # 1.查询书籍主键为4的出版社名称
    # 先查询书籍对象
    # book_obj = models.Book.objects.filter(pk=4).first()
    # 外键字段在书这里 所以是正向查询
    # res = book_obj.publish
    # print(res)
    # print(res.title)
    # print(res.addr)
# 2.查询书籍主键为3的作者姓名
    # 先查询书籍对象
    # book_obj = models.Book.objects.filter(pk=3).first()
    # 外键字段在书这里 所以是正向查询
    # res = book_obj.authors
    # print(res)  # app01.Author.None
    # res = book_obj.authors.all()
    # print(res)  # <QuerySet [<Author: 作者对象:oscar>, <Author: 作者对象:egon>]>
​
​
    # 3.查询作者jason的地址
    # 先查询jason数据对象
    # author_obj = models.Author.objects.filter(name='jason').first()
    # 外键字段在作者这里 所以是正向查询
    # res = author_obj.author_detail
    # print(res)
    # print(res.addr)
    # print(res.phone)
​
​
    # 4.查询东方出版社出版的书籍
    # 先查询出版社对象
    # publish_obj = models.Publish.objects.filter(title='东方出版社').first()
    # 外键字段在书那里自己没有 所以是反向
    # res = publish_obj.book_set
    # print(res)  # app01.Book.None
    # res = publish_obj.book_set.all()
    # print(res)
​
​
    # 5.查询jason写过的书籍
    # 先查询jason数据对象
    # author_obj = models.Author.objects.filter(name='jason').first()
    # 外键字段在书那里自己没有 所以是反向
    # res = author_obj.book_set
    # print(res)  # app01.Book.None
    # res = author_obj.book_set
    # print(res)  # app01.Book.None
    # res = author_obj.book_set.all()
    # print(res)  # app01.Book.None
​
​
    # 6.查询电话是120的作者
    # 先查询120数据对象
    # author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
    # 外键字段在作者那里本身没有 所以是反向
    # res = author_detail_obj.author
    # print(res)
    # print(res.name)
    # print(res.age)
    
    
    
    ########################基于双下滑线的跨表查询
    # 1.查询书籍主键为4的出版社名称
    # res = models.Book.objects.filter(pk=4).values('publish__title','publish__addr','title')
    # print(res)
# 2.查询书籍主键为3的作者姓名
    # res = models.Book.objects.filter(pk=3).values('authors__name')
    # print(res)
# 3.查询作者jason的地址
    # res = models.Author.objects.filter(name='jason').values('author_detail__addr','name','age')
    # print(res)
# 4.查询北方出版社出版的书籍名称
    # res = models.Publish.objects.filter(title='北方出版社').values('book__title')
    # print(res)
# 5.查询jason写过的书籍
    # res = models.Author.objects.filter(name='jason').values('book__title','name','age')
    # print(res)
# 6.查询电话是120的作者
    # res = models.AuthorDetail.objects.filter(phone=120).values('author__name','author__age','addr')
    # print(res)
    
    
    
    ############进阶操作#############
    # 1.查询书籍主键为4的出版社名称
    # res = models.Book.objects.filter(pk=4).values('publish__title','publish__addr','title')
    # print(res)
    # 反向查询高阶部分
    # res = models.Publish.objects.filter(book__pk=4)
    # print(res)
# 2.查询书籍主键为3的作者姓名
    # res = models.Book.objects.filter(pk=3).values('authors__name')
    # print(res)
    # 反向查询高阶部分
    # res = models.Author.objects.filter(book__pk=3)
    # print(res)
# 3.查询作者jason的地址
    # res = models.Author.objects.filter(name='jason').values('author_detail__addr','name','age')
    # print(res)
    # 反向查询高阶部分
    # res = models.AuthorDetail.objects.filter(author__name='jason')
    # print(res)
​
​
    # 查询书籍主键为3的作者的电话号码
    # res = models.Book.objects.filter(pk=3).values('authors__author_detail__phone')
    # print(res)
# res = models.AuthorDetail.objects.filter(author__book__pk=3).values('phone')
    # print(res)
# res = models.Author.objects.filter(book__pk=3).values('author_detail__phone')
    # print(res)

 

 

3 F查询

   # F查询
    from django.db.models import F
    # 1.查询库存数大于卖出数的书籍
    # res = models.Book.objects.filter(kucun__gt=F('maichu'))
    # print(res)
    # 2.将所有的书籍价格上涨100块
    # res = models.Book.objects.update(price=F('price') + 100)
    # print(res)
    # 3.将所有的书籍名称加上"爆款"后缀
    '''针对字符串不能直接拼接 需要额外导入模块操作'''
    # models.Book.objects.update(title=F('title') + '爆款')
    # from django.db.models.functions import Concat
    # from django.db.models import Value
    # ret3 = models.Book.objects.update(title=Concat(F('title'), Value('爆款')))

 

4 Q查询

   # 1.查询书名是三国演义爆款或者库存是100的书籍
    '''filter()括号内可以写多个参数 逗号隔开  默认只支持and连接'''
    from django.db.models import Q
    # res = models.Book.objects.filter(title='三国演义爆款',kucun=100)
    # print(res)
    # res1 = models.Book.objects.filter(Q(title='三国演义爆款'),Q(kucun=100))  # and
    # res1 = models.Book.objects.filter(Q(title='三国演义爆款')|Q(kucun=100))  # or
    # res1 = models.Book.objects.filter(~Q(title='三国演义爆款')|Q(kucun=100))  # not
    # print(res1.query)
    '''Q进阶用法'''
    # condition = input('请输入你需要按照什么字段查询数据>>>:')
    # data = input('请输入你需要查询的数据名称>>>:')
    # q = Q()  # 生成一个Q对象
    # q.children.append((condition,data))
    # res = models.Book.objects.filter(q)
    # print(res)
    q = Q()
    q.connector = 'or'  # 可以修改连接条件
    q.children.append(('title__contains',''))
    q.children.append(('price__gt',200))  # 可以添加多个条件 并且也是and关系
    res = models.Book.objects.filter(q)
    print(res)
    print(res.query)

 

 

5 事务

"""
1.事务四大特性    ACID
    原子性
    一致性
    独立性
    持久性
2.数据库设计三大范式
    课下百度搜索自己概括
​
MySQL
    start transcation
    commit
    rollback
"""
from django.db import transaction
    try:
        with transaction.atomic():
            # 创建一条订单数据
            models.Order.objects.create(num="110110111", product_id=1, count=1)
            # 能执行成功
            models.Product.objects.filter(id=1).update(kucun=F("kucun") - 1, maichu=F("maichu") + 1)
    except Exception as e:
        print(e)

 

6 执行原生SQL语句

res = models.Book.objects.raw('select * from app01_book')
for i in res:
    print(i)
 

7 模型层字段及参数

models.AutoField(primary_key=True)
models.CharField(max_length=32)         # varchar(32)
models.IntergeField()                   # int()
models.DateField()                      # date
models.DateTimeField()                  # datetime
    auto_now
    auto_now_add
models.DecimalField()                   # float()
models.BooleanField()
    给这个字段传布尔值会自动转换成数字0或1
    一般用在状态二选一
TextField()
     存储大段文本(bbs项目会使用)
EmailField()
    存储邮箱格式数据
FileField()
    存储数据路径(bbs项目会使用)
​
"""自定义字段"""
from django.db.models import Field
​
​
class MyCharField(Field):
    def __init__(self,max_length,*args,**kwargs):
        self.max_length = max_length
        super().__init__(max_length=max_length,*args,**kwargs)
​
    def db_type(self, connection):
        return 'char(%s)'%self.max_length

 

 

8 常见参数

max_length
varbose_name
default
null
auto_now
auto_now_add
to
unique
db_index
choices
​
# choices参数
创建用户表
    性别
        两到三种状态
    学历
        也是有限个
    在职状态
        也是有限个
    婚姻
        也是有限个
    ...
"""针对某个字段可以列举完全的情况 一般都是使用choices参数"""
class Server(models.Model):
    host = models.CharField(max_length=32)
​
    status_choices = (
        (1,'在线'),
        (2,'待上线'),
        (3,'宕机'),
        (4,'待上架')
    )
    status = models.IntegerField(choices=status_choices)
​
    desc_choices = (
        ('哈哈','哈哈哈哈哈哈'),
        ('呵呵','呵呵呵呵呵呵'),
        ('嘿嘿','嘿嘿嘿嘿嘿嘿'),
        ('嘻嘻','嘻嘻嘻嘻嘻嘻'),
    )
    desc = models.CharField(max_length=32,choices=desc_choices)
​
# 获取对应关系
.get_字段名_display()

9 ORM查询优化

# 惰性查询
    用不到的数据即使写了orm语句也不会执行
1.only与defer
2.select_related与prefech_related
​
​
# 1.only与defer
# res = models.Book.objects.values('title')  # 列表套字典
# res1 = models.Book.objects.only('title')  # 列表套对象
    # print(res1)
    # for i in res1:
    #     # print(i.title)
    #     print(i.price)
    """
    only括号内写什么字段
        生成的对象就含有对应的属性 在查找该属性的时候不再走数据库查询
        但是一旦查找括号内没有的字段属性 则每次都会走数据库查询
​
    """
    # res1 = models.Book.objects.defer('title')
    # # print(res1)  # 列表套对象
    # for i in res1:
    #     # print(i.title)
    #     print(i.title)
    """
    defer与only刚好相反
        生成的对象就不含有对应的属性 在查找该属性的时候需要每次走数据库查询
        但是一旦查找括号内没有的字段属性 则不需要走数据库查询
    """
    # res = models.Book.objects.filter(pk=3).first()
    # print(res.publish.title)
​
​
    # res = models.Book.objects.select_related('publish')
    # for i in res:
    #     print(i.publish.title)
    """
    select_related相当于连表操作
        先将models后面的表和括号内外键字段关联的表连接起来
        之后一次性把所有的数据封装到数据对象中
    """
    res = models.Book.objects.prefetch_related('publish')
    for i in res:
        print(i.publish.title)
    """
    prefetch_related相当于子查询
        先查询models后面的表的所有的数据
        然后将括号内关联的表的数据全部查询出来
        之后整合到一起
    """
 

 

 

 

posted @ 2021-06-02 21:23  Jerry`  阅读(49)  评论(0编辑  收藏  举报