模型层字段-多表查询-神奇的双下划线查询-F,Q查询

Django ORM中常用的字段和参数

常用字段

AutoField

int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。

IntegerField

一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)

CharField

字符类型,必须提供max_length参数, max_length表示字符长度。

DateField

日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。

DateTimeField

日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

TextField(Field)
   - 文本类型
   用来存大段文本
  
  FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      用户上传的文件会自动放到等号后面指定的文件路径中
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

书写格式一般如下:

自定义对应于数据库的char类型

 

 然后在model.py里建表模型的时候可以直接应用:

 

字段参数

null

用于表示某个字段可以为空。

unique

如果设置为unique=True 则该字段在此表中必须是唯一的 。

db_index

如果db_index=True 则代表着为此字段设置索引。

default

为该字段设置默认值。

DateField和DateTimeField

auto_now_add

配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

auto_now

配置上auto_now=True,每次更新数据记录的时候会更新该字段。

 

关系字段

ForeignKey

外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中'多'的一方。

ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。

字段参数

to

设置要关联的表

to_field

设置要关联的表的字段

on_delete

当删除关联表中的数据时,当前表与其关联的行的行为。

models.CASCADE

删除关联数据,与之关联也删除

db_constraint

是否在数据库中创建外键约束,默认为True。

 

常用的多表关系查询的外键字段创建

一对一字段:OneToOneField
多对多字段:ManyToManyField
一对多字段:ForeignKey

针对外键字段

  当你在使用django2.x版本的时候,建外键字段时,需要手动添加几个关键字段参数

models.cascade
db_constraints

Django终端打印SQL语句

把参数放在settings.py配置文件中,会在终端打印出相应的mysql查询语句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

 配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上

也可以用.query大方式查看查询语句:

 

 13个必会操作总结

返回QuerySet对象的方法有

all()

filter()

exclude()

order_by()

reverse()

distinct()

特殊的QuerySet

values()       返回一个可迭代的字典序列

values_list() 返回一个可迭代的元祖序列

返回具体对象的

get()

first()

last()

返回布尔值的方法有:

exists()

返回数字的方法有

count()

 

神奇的双下滑查询 

   对应MySQL的查询语句形成对比记忆,方法和查询的方法类似

# 价格 大于 小于 大于等于 小于等于
filter(price__gt='90')
filter(price__lt='90')
filter(price_gte='90')
filter(price_lte='90')

# 存在与某几个条件中
filter(price__in=['11','22','33'])
# 在某个范围内
filter(price__range=[50,90])

# 模糊查询
filter(title__contains='西')
filter(title__icontains='P')

# 以什么开头 以什么结尾

# 按年查询
filter(create_time__year='2017')

 

多表查询:跨表查询,连表查询

书写测试代码脚本:

 

 一对多的字段的增删改查

增操作:关键字 create

改操作:关键字 update

 

查数据:常用的13种

# < 1 > all(): 查询所有结果
# < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象

# < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
# 如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象) # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 # < 5 > order_by(*field): 对查询结果排序('-id') / ('price') # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
# < 7 > count(): 返回数据库中匹配查询(QuerySet) # 的对象数量。 # < 8 > first(): 返回第一条记录 # < 9 > last(): 返回最后一条记录 # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 # model的实例化对象,而是一个可迭代的字典序列
# < 12 > values_list(*field): 它与values()
# 非常相似,它返回的是一个元组序列,values返回的是一个字典序列

# < 13 > distinct(): 从返回结果中剔除重复纪录 # # 必须完全一样才可以去重(意味着带了id就没有意义了) # # res = models.Book.objects.all().values('name').distinct() 先查一个重复的值再去重


# 查询书籍名字中包含p的
"""原生sql语句 模糊匹配
like % _
"""
# res = models.Book.objects.filter(title__contains='p') # 仅仅只能拿小写p
# res = models.Book.objects.filter(title__icontains='p') # 忽略大小写

 

删除操作: delete

多对多字段的增删改查

增操作:add()

add():添加操作,括号内既可以传数字也可以传对象,并且支持一次性传多个,逗号隔开即可

 

 改操作:set()

  set()括号内需要传一个可迭代对象,可迭代对象中,可以是多个数字组合,也可以是多个对象组合,但不能 混合使用

 

删除操作:remove()

  remove() 括号内既可以传数字,也可以传对象,并且支持传多个,逗号隔开即可.

 

 清空操作:clear(),括号内不需要传任何参数

 

 跨表查询

1.对象查找(跨表)

语法:

对象.关联字段.字段

要点:先拿到对象,再通过对象去查对应的外键字段,分两步

示例:

book_obj = models.Book.objects.first()  # 第一本书对象(第一步)
print(book_obj.publisher)  # 得到这本书关联的出版社对象
print(book_obj.publisher.name)  # 得到出版社对象的名称

2.字段查找(跨表)

语法:

关联字段__字段

要点:利用Django给我们提供的神奇的双下划线查找方式

models.Book.objects.all().values("publisher__name")
#拿到所有数据对应的出版社的名字,神奇的下划线帮我们夸表查询

反向操作(两种方式)

1.对象查找

语法:

obj.表名_set

要点:先拿到外键关联多对一,一中的某个对象,由于外键字段设置在多的一方,所以这里还是借用Django提供的双下划线来查找

publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
titles = books.values_list("title")  # 找到第一个出版社出版的所有书的书名

正向与反向的概念

  口诀"正向查询按外键字段,反向查询按表名小写"

# 跨表查询(***)
    """
    正向与反向的概念
    
    # 一对一
    # 正向:author---关联字段在author表里--->authordetail    按字段
    # 反向:authordetail---关联字段在author表里--->author    按表名小写
    
    # 一对多
    # 正向:book---关联字段在book表里--->publish  按字段
    # 反向:publish---关联字段在book表里--->book  按表名小写_set.all() 因为一个出版社对应着多个图书
    
    # 多对多
    # 正向:book---关联字段在book表里--->author     按字段
    # 反向:author---关联字段在book表里--->book     按表名小写_set.all() 因为一个作者对应着多个图书
    
    正向查询按外键字段
    反向查询按表名小写
    
    """
    """基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)"""
    """

例题:

1.查询书籍id是1 的出版社名称

book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)
print(book_obj.publish.addr)

2、查询书籍id是2 的作者姓名

# book_obj = models.Book.objects.filter(pk=2).first()
   print(book_obj.authors)  # app01.Author.None
    # print(book_obj.authors.all())
    # res = book_obj.authors.all()
    # for r in res:
    #     print(r.name)

3、查询出版社是东方出版社出版的书籍

publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set)  # app01.Book.None
print(publish_obj.book_set.all())

4、查询电话号码是130的作者姓名

author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
print(author_detail_obj.author.name) print(author_detail_obj.author.age)

  当你反向查询的结果是多个的时候 就需要加_set,否则直接表明小写即可

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

  联想MySQL:left join 左连接,inner join 内连接,right 右连接,union  全连接

1、查询jason作者的手机号

 

 2、查询手机号是130的作者年龄

 

3、查询书籍id=1的作者的电话号码

 

 4、查询北方出版社出版的价格大于19的书

 

 聚合查询  

  关键字:aggregate ,类似mysql的聚合函数,最大值,最小值,平均值,总计,sum(总数)

from django.db.models import Max,Min,Count,Avg,Sum

1、统计所有书的总价格

 

分组查询

  结合聚合函数+()使用,关键字:annotate

1、统计每一本书的作者个数

 

2、统计出每个出版社卖的最便宜的书的价格

 

 3、统计不止一个作者的图书

 

 F查询:

  F是个模块,需要导入使用

  F查询的本质就是从数据库中获取某个字段的值来进行一系列的操作

1、查询库存数大于卖出的书籍

 

2、将书籍库存数全部增加100

 

 3、把所有书名后面加上“新款“

拼接需要导入模块:Conact、Value

 

Q查询:

  Q也是一个模块需要导入,才能使用

  进行与或非等复杂的组合操作( |,&,&~Q,~(非))

filter() 等方法中逗号隔开的条件是与的关系。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

例子:查询书籍名称是三国演义或者价格是444.44

 

 Q的高级用法:

  更改查询中的条件,用q.connector修改括号内的属性

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  



 

 

 

 

  

 

 

 

 

 

 

 

 

 


 

posted @ 2019-09-20 00:08  游走De提莫  阅读(306)  评论(0编辑  收藏  举报