django-orm进阶操作

进阶操作

# 获取个数
        #
        # models.Tb1.objects.filter(name='seven').count()

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

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

        # isnull
        # Entry.objects.filter(pub_date__isnull=True)

        # contains
        #
        # models.Tb1.objects.filter(name__contains="ven")
        # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
        # models.Tb1.objects.exclude(name__icontains="ven")

        # range
        #
        # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and

        # 其他类似
        #
        # startswith,istartswith, endswith, iendswith,

        # order by
        #
        # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
        # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc

        # group by
        #
        # from django.db.models import Count, Min, Max, Sum
        # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
        # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

        # limit 、offset
        #
        # models.Tb1.objects.all()[10:20]

        # regex正则匹配,iregex 不区分大小写
        #
        # Entry.objects.get(title__regex=r'^(An?|The) +')
        # Entry.objects.get(title__iregex=r'^(an?|the) +')

        # date
        #
        # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
        # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

        # year
        #
        # Entry.objects.filter(pub_date__year=2005)
        # Entry.objects.filter(pub_date__year__gte=2005)

        # month
        #
        # Entry.objects.filter(pub_date__month=12)
        # Entry.objects.filter(pub_date__month__gte=6)

        # day
        #
        # Entry.objects.filter(pub_date__day=3)
        # Entry.objects.filter(pub_date__day__gte=3)

        # week_day
        #
        # Entry.objects.filter(pub_date__week_day=2)
        # Entry.objects.filter(pub_date__week_day__gte=2)

        # hour
        #
        # Event.objects.filter(timestamp__hour=23)
        # Event.objects.filter(time__hour=5)
        # Event.objects.filter(timestamp__hour__gte=12)

        # minute
        #
        # Event.objects.filter(timestamp__minute=29)
        # Event.objects.filter(time__minute=46)
        # Event.objects.filter(timestamp__minute__gte=29)

        # second
        #
        # Event.objects.filter(timestamp__second=31)
        # Event.objects.filter(time__second=2)
        # Event.objects.filter(timestamp__second__gte=31)

进阶操作

高级操作

extra
在QuerySet的基础上继续执行子语句
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
select-select_params

tmp = models.Book.objects.all().extra(select={"n":"select count(1) from app05_book"})
for i in tmp:
    print(i.title, i.n)
书一 6
书二 6
书三(第) 6
书四(第) 6
书五(第) 6
书六(第) 6

select占位符

tmp = models.Book.objects.all().extra(select={"n":"select count(1) from app05_book WHERE id>%s"},select_params=[3,])
for i in tmp:
    print(i.title, i.n)
书一 3
书二 3
书三(第) 3
书四(第) 3
书五(第) 3
书六(第) 3

where-params

models.Book.objects.extra(where=["title=%s"],params=["书一"])
<QuerySet [<Book: 书一>]>
models.Book.objects.extra(where=["title='书一' or title='书二'"])
<QuerySet [<Book: 书一>, <Book: 书二>]>

and关系

models.Book.objects.extra(where=["title='书一'","id=2"])
<QuerySet []>

举个例子:

models.UserInfo.objects.extra(
                    select={'newid':'select count(1) from app01_usertype where id>%s'},
                    select_params=[1,],
                    where = ['age>%s'],
                    params=[18,],
                    order_by=['-age'],
                    tables=['app01_usertype']
                )
                """
                select 
                    app01_userinfo.id,
                    (select count(1) from app01_usertype where id>1) as newid
                from app01_userinfo,app01_usertype
                where 
                    app01_userinfo.age > 18
                order by 
                    app01_userinfo.age desc
                """


# 执行原生SQL
# 更高灵活度的方式执行原生SQL语句
# from django.db import connection, connections
# cursor = connection.cursor()  # cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()

QuerySet高级操作

去重

def distinct(self, *field_names)

models.Book.objects.values("title").distinct()
<QuerySet [{'title': '书一'}, {'title': '书三(第)'}, {'title': '书四(第)'}, {'title': '书五(第)'}, {'title': '书六(第)'}]>

select_related实现表之间进行一对一和多对一优化

def select_related(self, *fields)
    性能相关:表之间进行join连表操作,一次性获取关联的数据。
    总结:
    1. select_related主要针一对一和多对一关系进行优化。
    2. select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。

实例代码如下:

tmp = models.Book.objects.all()
for i in tmp:
    print(i.publisher.name)
沙河出版社
沙河出版社
三里屯
五道口
国贸
五道口

a2 = models.Book.objects.all().select_related("publisher")
for i in a2:
    print(i.publisher.name)
沙河出版社
沙河出版社
五道口
五道口
三里屯
国贸

以上代码中第一种查询方式会查询数据库六次,第二种方式会查询数据库次数为1次

prefetch_related实现表之间进行一对多和多对多优化
只能正向查询~且不能跨表

def prefetch_related(self, *lookups)
    性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。

    总结:
    1. 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。
    2. prefetch_related()的优化方式是分别查询每个表,然后用Python处理他们之间的关系。

实例代码如下:

tmp = models.Author.objects.all().prefetch_related("books")
for i in tmp:
    print(i.books.all())
<QuerySet [<Book: 书一>, <Book: 书一>]>
<QuerySet [<Book: 书一>, <Book: 书三(第)>]>
<QuerySet [<Book: 书一>]>
<QuerySet []>

defer

 def defer(self, *fields):
    models.UserInfo.objects.defer('username','id')
    或
    models.UserInfo.objects.filter(...).defer('username','id')
    #映射中排除某列数据

实例代码如下:

a = models.Author.objects.all().defer("name")
for i in a:
    print(i)
小一
小二
小三
小四
a = models.Author.objects.all().defer("name").values()
for i in a:
    print(i)
{'id': 1, 'name': '小一', 'author_detail_id': 1}
{'id': 2, 'name': '小二', 'author_detail_id': 2}
{'id': 3, 'name': '小三', 'author_detail_id': 3}
{'id': 4, 'name': '小四', 'author_detail_id': 4}

a = models.Author.objects.all().defer(“name”).values()
虽然在查询中排除name字段,但是在循环中如果要输出关于name的信息,那么依然会继续查询输出name

only


 def only(self, *fields):
    #仅取某个表中的数据
     models.UserInfo.objects.only('username','id')
     或
     models.UserInfo.objects.filter(...).only('username','id')

示例代码如下:

a = models.Author.objects.only("name")
for i in a:
    print(i)
小一
小二
小三
小四

raw执行原生SQL
执行原生SQL

tmp = models.Author.objects.raw("select * from app05_author")
for i in tmp:
    print(i.name)
小一
小二
小三
小四

为原生SQL设置参数

a = models.Book.objects.raw("select id from app05_book WHERE id>%s",params=[3,])
for i in a:
    print(i)
书四(第)
书五(第)
书六(第)

dates

def dates(self, field_name, kind, order='ASC'):
    # 根据时间进行某一部分进行去重查找并截取指定内容
    # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
    # order只能是:"ASC"  "DESC"
    # 并获取转换后的时间
        - year : 年-01-01
        - month: 年-月-01
        - day  : 年-月-日

    models.DatePlus.objects.dates('ctime','day','DESC')

示例代码如下:
这里写图片描述

models.Book.objects.all().dates("publish_day","year","DESC")
<QuerySet [datetime.date(2018, 1, 1), datetime.date(2017, 1, 1)]>

models.Book.objects.all().dates("publish_day","month","DESC")
<QuerySet [datetime.date(2018, 4, 1), datetime.date(2018, 1, 1), datetime.date(2017, 1, 1)]>

models.Book.objects.all().dates("publish_day","day","DESC")
<QuerySet [datetime.date(2018, 4, 12), datetime.date(2018, 1, 29), datetime.date(2018, 1, 25), datetime.date(2018, 1, 19), datetime.date(2018, 1, 11), datetime.date(2017, 1, 18)]>

datetimes

def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
    # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
    # kind只能是 "year", "month", "day", "hour", "minute", "second"
    # order只能是:"ASC"  "DESC"
    # tzinfo时区对象
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))

    """
    pip3 install pytz
    import pytz
    pytz.all_timezones
    pytz.timezone(‘Asia/Shanghai’)
    """

bulk_create
参数为一次性插入的个数

objs = [models.Publisher(name="aaa",addr="aaa"),models.Publisher(name="bbb",addr="bbb")]
models.Publisher.objects.bulk_create(objs,2)
[<Publisher: aaa>, <Publisher: bbb>]

get_or_create
# 如果存在,则获取,否则,创建
# defaults 指定创建时,其他字段的值

models.Publisher.objects.get_or_create(name="沙河出版社")
(<Publisher: 沙河出版社>, False)

models.Publisher.objects.get_or_create(name="沙河出版社1")
(<Publisher: 沙河出版社1>, True)

models.Publisher.objects.get_or_create(name="沙河出版1",addr="sss")
(<Publisher: 沙河出版1>, True)

models.Publisher.objects.get_or_create(name="沙河版1",defaults={"addr":"sdfsdsf"})
(<Publisher: 沙河版1>, True)

这里写图片描述

update_or_create
如果存在,则更新,否则,创建
defaults 指定创建时或更新时的其他字段

obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})

in_bulk
# 根据主键ID进行查找
id_list = [11,21,31]
models.DDD.objects.in_bulk(id_list)

from app05 import models
models.Book.objects.in_bulk([1,2,3])
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.001) SELECT VERSION(); args=None
(0.002) SELECT `app05_book`.`id`, `app05_book`.`title`, `app05_book`.`price`, `app05_book`.`publish_day`, `app05_book`.`publisher_id` FROM `app05_book` WHERE `app05_book`.`id` IN (1, 2, 3); args=(1, 2, 3)
{1: <Book: 书一>, 2: <Book: 书一>, 3: <Book: 书三(第)>}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值