Django ORM参数与操作

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,相当于Python中的datetime.datetime()实例。

字段参数

null

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

unique

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

db_index

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

default

为该字段设置默认值。

auto_now

每次操作改数据都会自动更新时间

auto_now_add

新增数据的时候会将当前时间自动添加,后续的修改该字段不会自动更新

单独的py文件测试ORM操作需要配置的参数

# 可以在manage.py文件中复制
import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE","day58.settings")
    import django
    django.setup()
    from app01 import models # 这一句话必须在这下面导入

img

单表查询

查询方法

all( ):查询所有结果

img

filter(kwargs):包含了与所给筛选条件相匹配的对象

img

get(kwargs):返回了所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

img

exclude(kwargs):包含了与所给筛选条件不匹配的对象

img

order_by(*field):对查询结果排序

reverse():对查询结果反向排序 >>> 要先有排序才能反向

count():返回数据库中匹配查询

img

first():返回第一条记录

img

last():返回最后一条记录

exists():若果QuerySet包含数据,就返回True,否则返回False

values(*field):返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

img

values_list(*field):它与values()非常相似,它返回的是一个元组序列

img

distinct():从返回结果中剔除重复纪录

查询方法总结

返回QuertSet对象的方法有

all()
filter()
exclude()
order_by()
reverse()
distinct()

特殊的QuerySet

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

values_list:返回一个可迭代的元组序列

返回具体对象

get()
first()
last()

返回布尔值的方法

exists()

返回数字的方法

count()

Django终端打印SQL语句

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终端上

单表查询之神奇的双下划綫

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据

models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

models.Tb1.objects.filter(name__contains="ven")  # 获取name字段包含"ven"的

models.Tb1.objects.filter(name__icontains="ven") # icontains忽略大小写

models.Tb1.objects.filter(id__range=[1, 3])      # id范围是1到3的,等价于SQL的bettwen and

 res = models.User.objects.filter(name__startswith='j')  # 查询名字以j开头的用户
    
res = models.User.objects.filter(name__endswith='n')    # 查询名字以n结尾的用户  

# date字段还可以:
models.Class.objects.filter(first_day__year=2017)
# date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据

多表查询

表与表之间的关系

一对一(OneToOneField)

一对一字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面

一对多(Foreignkey)

一对多字段建在多的那一方

多对多(ManyToManyField)

多对多字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面

多表查询方法

新增

# 直接写id
models.Book.objects.create(title='红楼梦',prrice=66.66,publish_id=1)
# 传数据对象
publish_obj = model.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='三国演义',price=199.99,publish=publish_obj)

修改

# queryset修改
models.Book.objects.filter(pk=1).update(publish_id=3)
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
# 对象修改
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.publish_id = 3  # 点表中真实存在的字段名
book_obj.save()
publish_obj = models.Publish.objects.filter(pk=2).first()
book_obj.publish = publish_obj  # 点orm中字段名 传该字段对应的表的数据对象
book_obj.save()

删除

# queryset删除
models.Book.objects.filter(pk=1).delete()
models.Publish.objects.filter(pk=1).delete()
# 对象删除
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.delete()

多对多表操作

添加绑定关系(add( ):add支持传数字或对象,并且都可以传多个值)

# 例如给书籍绑定与作者之间的关系
# 通过id添加
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.add(1)
book_obj.authors.add(2,3)

# 通过对象添加
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=3).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1)

修改绑定关系(set( ):set传的必须是可迭代对象)

book_obj = models.Book.objects.filter(pk=3).first()
# 通过id修改
book_obj.authors.set((1,))
# 支持传多个
book_obj.authors.set((1,2,3))

# 通过对象修改
author_list = models.Author.objects.all()
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.set(author_list)

删除绑定关系(remove( ))

book_obj = models.Book.objects.filter(pk=3).first()
# 通过id删除
book_obj.authors.remove(1)
book_obj.authors.remove(2,3)

# 通过对象删除
author_obj = models.Author.objects.all().first()
author_list = models.Author.objects.all()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(*author_list)  # 需要将queryset打散

清空绑定关系(clear( ):清空当前表记录对应的绑定关系)

book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.clear()

正反向操作

# 正向与方向的概念解释

# 一对一
# 正向:author---关联字段在author表里--->authordetail		按字段
# 反向:authordetail---关联字段在author表里--->author		按表名小写
  
# 一对多
# 正向:book---关联字段在book表里--->publish		按字段
# 反向:publish---关联字段在book表里--->book		按表名小写_set.all() 因为一个出版社对应着多个图书

# 多对多
# 正向:book---关联字段在book表里--->author		按字段
# 反向:author---关联字段在book表里--->book		按表名小写_set.all() 因为一个作者对应着多个图书
  
# 连续跨表
	# 查询图书是三国演义的作者的手机号,先查书,再正向查到作者,在正向查手机号

# 总结:基于对象的查询都是子查询,这里可以用django配置文件自动打印sql语句的配置做演示

基于对象的表查询

正向

# 查询书籍是三国演义的出版社邮箱
book_obj = models.Book.objects.filter(title='三国演义').first()
print(book_obj.publish.email)

# 查询书籍是水浒传的作者的姓名
book_obj = models.Book.objects.filter(title='水浒传').first
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())

# 查询作者为jason电话号码
user_obj = models.Author.objects.filter(name='jason').first()
print(user_obj.phone)

反向

# 查询出版社是东方出版社出版的书籍               一对多字段的反向查询
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())

# 查询作者jason写过的所有的书                   多对多字段的反向查询
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all())

# 查询作者电话号码是110的作者姓名                一对一字段的反向查询
authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first()
print(authordetail_obj.author.name)

基于双下划线的查询

正向

# 查询书籍为三国演义的出版社地址
models.Book.objects.filter(title='三国演义').values('publish__addr','title')

# 查询书籍为水浒传的作者的姓名
models.Book.objects.filter(title='水浒传').values('authors__name','title')

# 查询作者为jason的家乡
model.Author.object.filter(name='jason').values('authordetail__addr')

反向

# 查询南方出版社出版的书名
models.Publish.objects.filter(name='南方出版社').values('book__title')

# 查询电话号码为120的作者姓名
models.AuthorDetail.objects.filter(phone=120).values('author__name')

# 查询作者为jason的写的书的名字
models.Author.object.filter(name='jason').values('book__title')

# 查询书籍为三国演义的作者的电话号码
models.Book.objects.filter(title='三国演义').values('authors__authordetail__phone')    

聚合查询(aggregate)

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

# 查询id为3书籍的作者个数
models.Book.object.filter(pk=3).aggregate(count_num=Count('authors'))

# 查询所有出版社出版的书的平均价格
models.Publish.object.aggregate(avg_price=Avg('book__price'))

# 统计东方出版社出版的书籍的个数
models.Publish.object.filter(name='东方出版社').aggregate(count_num=Count('book__id'))

分组查询 (annotate)

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

# 统计每个出版社出版的书的平均价格
models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price')

# 统计每一本书的作者个数
models.Book.objects.annotate(count_num=Count('authors')).values('title','count_num')

# 统计出每个出版社卖的最便宜的书的价格
models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')

# 查询每个作者出的书的总价格
models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
posted @ 2019-06-12 20:11  Lip&Hip  阅读(560)  评论(0)    收藏  举报