Django之ORM操作(三) ---- 第14章

1. all

獲取所有的數據對象,參數使用參考:

def all(self):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    return HttpResponse()
3. filter

條件查詢,條件也可以是字典類型,參數使用參考:

def filter(self, *args, **kwargs):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    # result = models.UserInfo.objects.filter(id__gt=1)
    # result = models.UserInfo.objects.filter(id__lt=1)
    # result = models.UserInfo.objects.filter(id__gte=1)
    result = models.UserInfo.objects.filter(id__lte=1)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE `app01_userinfo`.`id` <= 1
    """
    result = models.UserInfo.objects.filter(id__in=[1, 2, 3])
    """
    print(result.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" 
    FROM "app01_userinfo" 
    WHERE "app01_userinfo"."id" IN (1, 2, 3)
    """
    result = models.UserInfo.objects.filter(id__range=[1, 3])
    """
    print(result.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" 
    FROM "app01_userinfo" 
    WHERE "app01_userinfo"."id" BETWEEN 1 AND 3
    """
    result = models.UserInfo.objects.filter(name__startswith='xxx')
    """
    print(result.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" 
    FROM "app01_userinfo" 
    WHERE "app01_userinfo"."name" LIKE xxx%
    """
    result = models.UserInfo.objects.exclude(id=1)
    """
    print(result.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" 
    FROM "app01_userinfo" 
    WHERE NOT ("app01_userinfo"."id" = 1)
    """
    result = models.UserInfo.objects.filter(name__endswith='xxx')
    """
    print(result.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" 
    FROM "app01_userinfo" 
    WHERE "app01_userinfo"."name" LIKE %xxx
    """
    result = models.UserInfo.objects.filter(id=1, name='thanlon')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` = 1 AND `app01_userinfo`.`name` = thanlon)
    """
    condition = {
        'id': 1,
        'name': 'thanlon'
    }
    result = models.UserInfo.objects.filter(**condition)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` = 1 AND `app01_userinfo`.`name` = thanlon)
    """
    return HttpResponse()
2. order_by

order_by用於排序,參數使用參考:

def order_by(self, *field_names):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    # 1、按照id從小到大排序
    result = models.UserInfo.objects.all().order_by('id')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    ORDER BY `app01_userinfo`.`id` ASC
    """
    # 2、按照id從小到大排序
    result = models.UserInfo.objects.all().order_by('-id')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    ORDER BY `app01_userinfo`.`id` DESC
    """
    # 3、按照id從大到小排序,如果有重複的按照name從小到大排序
    result = models.UserInfo.objects.all().order_by('-id', 'name')
    print(result.query)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    ORDER BY `app01_userinfo`.`id` DESC, `app01_userinfo`.`name` ASC
    """
    return HttpResponse()
2. reverse

reverse用來對查詢結果進行倒序排序,只有在使用order_by之後纔會有用,參數使用參考:

def reverse(self):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().reverse()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    result = models.UserInfo.objects.all().reverse().order_by('id')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    ORDER BY `app01_userinfo`.`id` DESC
    """
    result = models.UserInfo.objects.all().order_by('id').reverse()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    ORDER BY `app01_userinfo`.`id` DESC
    """
    return HttpResponse()
2. defer

映射中排除某列數據,id列不可以去除,參數:

def defer(self, *fields):
	pass

使用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    # id列不可使用defer來去除
    result = models.UserInfo.objects.all().defer('id','name','age')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`ut_id` FROM `app01_userinfo`
    """
    return HttpResponse()
8. only

只取某些列,參數使用參考:

def only(self, *fields):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().only('id','age')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`age` 
    FROM `app01_userinfo`
    """
    return HttpResponse()
3. annotate

annotate可以實現聚合分組查詢,參數使用參考:

def annotate(self, *args, **kwargs):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models


def user_list(request):
    result = models.UserInfo.objects.values('ut_id')
    result = models.UserInfo.objects.values('ut_id').annotate()
    """
    print(result.query)
    SELECT `app01_userinfo`.`ut_id` FROM `app01_userinfo`
    """
    from django.db.models import Count, Min, Max, F, Q
    result = models.UserInfo.objects.values('ut_id').annotate(xxx=Count('id'))
    """
    print(result.query)
    SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id`) AS `xxx` 
    FROM `app01_userinfo` 
    GROUP BY `app01_userinfo`.`ut_id` 
    ORDER BY NULL
    """
    result = models.UserInfo.objects.values('ut_id').annotate(xxx=Count('id')).filter(xxx__gt=2)
    """
    print(result.query)
    SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id`) AS `xxx` 
    FROM `app01_userinfo` GROUP BY `app01_userinfo`.`ut_id` 
    HAVING COUNT(`app01_userinfo`.`id`) > 2 
    ORDER BY NULL
    """
    result = models.UserInfo.objects.filter(id__gt=2).values('ut_id').annotate(xxx=Count('id')).filter(xxx__gt=2)
    """
    print(result.query)
    SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id`) AS `xxx` 
    FROM `app01_userinfo` 
    WHERE `app01_userinfo`.`id` > 2 
    GROUP BY `app01_userinfo`.`ut_id` 
    HAVING COUNT(`app01_userinfo`.`id`) > 2 
    ORDER BY NULL
    """
    return HttpResponse()
4. F

F會認爲是數據庫原有的值,參數:


應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    from django.db.models import F
    # 不可用來更新id的值,可能是id是自動遞增的原因
    result = models.UserInfo.objects.all().update(age=F("age") + 1)
    print(result)  # 更新的結果數
    return HttpResponse()
5. Q

Q是用來構造複雜的查詢條件,有兩種適用方式,一種是 對象方式

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    from django.db.models import Q
    result = models.UserInfo.objects.filter(Q(id__gt=1))
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE `app01_userinfo`.`id` > 1
    """
    result = models.UserInfo.objects.filter(Q(id__gt=1) & Q(name='thanlon'))
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` > 1 AND `app01_userinfo`.`name` = thanlon)
    """
    result = models.UserInfo.objects.filter(Q(id__gt=1) | Q(name='thanlon'))
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` > 1 OR `app01_userinfo`.`name` = thanlon)
    """
    return HttpResponse()

另一種是 方法 的方式:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    from django.db.models import Q
    q1 = Q()
    q1.connector = 'OR'
    q1.children.append(('id__gt', 1))
    q1.children.append(('id__lt', 5))
    print(q1)  # (OR: ('id__gt', 1), ('id__lt', 5))
    print(q1.children)  # [('id__gt', 1), ('id__lt', 5)]
    result = models.UserInfo.objects.filter(q1)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` > 1 OR `app01_userinfo`.`id` < 5)
    """

    q2 = Q()
    q2.connector = 'AND'
    q2.children.append(('age__gt', 16))
    q1.add(q2, 'OR')
    result = models.UserInfo.objects.filter(q1)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (`app01_userinfo`.`id` > 1 OR `app01_userinfo`.`id` < 5 OR `app01_userinfo`.`age` > 16)
    """
    
    q3 = Q()
    q3.add(q1, 'AND')
    q3.add(q2, 'AND')
    result = models.UserInfo.objects.filter(q3)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE ((`app01_userinfo`.`id` > 1 OR `app01_userinfo`.`id` < 5 OR `app01_userinfo`.`age` > 16) AND `app01_userinfo`.`age` > 16)
    """
    return HttpResponse()
6. extra

extra可以構造額外的查詢條件或者映射,如子查詢等,參數:

def extra(self, select=None, where=None, params=None, tables=None,
              order_by=None, select_params=None):
	pass     

子查詢:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().extra()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    result = models.UserInfo.objects.all().extra(select={'n': 'select count(1) from app01_usertype'})
    """
    print(result.query)
    SELECT (select count(1) from app01_usertype) AS `n`, `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    result = models.UserInfo.objects.all().extra(select={'n': 'select count(1) from app01_usertype where id>%s'},
                                                 select_params=[1])
    """
    print(result.query)
    SELECT (select count(1) from app01_usertype where id>1 and id<3) AS `n`, `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    result = models.UserInfo.objects.all().extra(
        select={'n': 'select count(1) from app01_usertype where id>%s and id<%s'},
        select_params=[1, 3])
    """
    print(result.query)
    SELECT (select count(1) from app01_usertype where id>1 and id<3) AS `n`, 
    `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    result = models.UserInfo.objects.all().extra(
        select={
            'n': 'select count(1) from app01_usertype where id>%s and id<%s',
            'm': 'select count(1) from app01_usertype where id>%s and id<%s'
        },
        select_params=[1, 2, 3, 4])
    """
    for obj in result:
        print(obj.name, obj.id, obj.n, obj.m)
    print(result.query)
    SELECT 
    (select count(1) from app01_usertype where id>1 and id<2) AS `n`, 
    (select count(1) from app01_usertype where id>3 and id<4) AS `m`, 
    `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    return HttpResponse()

根據條件查詢,與 filter 功能是相同的:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().extra(where=['id=1', 'name=thanlon'])
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (id=1) AND (name=thanlon)
    """
    result = models.UserInfo.objects.all().extra(where=['id=1 or id = %s', "name='%s'"], params=[2, 'thanlon'])
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    WHERE (id=1 or id = 2) AND (name='thanlon')
    """
    return HttpResponse()

在原來的基礎上增加查詢範圍:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().extra(tables=['app01_usertype'])
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` , `app01_usertype`
    """
    return HttpResponse()

進行排序,與 models.UserInfo.objects.all().order_by('-age') 具有相同的功能:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().extra(order_by=['-age'])
    print(result.query)
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo` 
    ORDER BY `app01_userinfo`.`age` DESC
    """
    return HttpResponse()

如果在extra中使用了order_by參數,又在extra之外使用了order_by('-age'),如models.UserInfo.objects.all().extra(order_by=['-age']).order_by('-age')或models.UserInfo.objects.all().order_by('-age').extra(order_by=['-age']),哪個在後面哪個就生效,其它extra中的參數也是一樣。

extra的綜合應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().extra(
        select={
            'm': 'select count(1) from app01_usertype where id>%s and id<%s',
            'n': 'select count(1) from app01_usertype where id>%s and id<%s'
        },
        select_params=[1, 2, 3, 4],
        where=['age>%s'],
        params=[18, ],
        order_by=['-age'],
        tables=['app01_usertype']
    )
    """
    print(result.query)
    SELECT 
        (select count(1) from app01_usertype where id>1 and id<2) AS `m`, 
        (select count(1) from app01_usertype where id>3 and id<4) AS `n`, 
        `app01_userinfo`.`id`, 
        `app01_userinfo`.`name`, 
        `app01_userinfo`.`age`, 
        `app01_userinfo`.`ut_id` 
        FROM `app01_userinfo` , `app01_usertype` 
        WHERE (age>18) 
        ORDER BY `app01_userinfo`.`age` DESC
    """
    return HttpResponse()
7. distinct

用於去重,使用參考:

def distinct(self, *field_names):
	pass

應用:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().values('id','name').distinct()
    """
    print(result.query)
    SELECT DISTINCT `app01_userinfo`.`id`, `app01_userinfo`.`name` 
    FROM `app01_userinfo`
    """
    return HttpResponse()

如果是PostgreSQL數據庫使用方式:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.distinct('id','name')
    """
    print(result.query)
    SELECT DISTINCT `app01_userinfo`.`id`, `app01_userinfo`.`name` 
    FROM `app01_userinfo`
    """
    return HttpResponse()
9. select_related

與性能相關,表之間進行 join 連表操作,一次性獲取關聯數據:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    result = models.UserInfo.objects.all().select_related()
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id`, `app01_usertype`.`id`, `app01_usertype`.`title` 
        FROM `app01_userinfo`
        INNER JOIN `app01_usertype`
        ON (`app01_userinfo`.`ut_id` = `app01_usertype`.`id`)
    """
    return HttpResponse()
10. prefetch_related

性能相關,多表連表操作時速度會慢,使用其執行多次SQL查詢在Python代碼中實現連表操作:

from django.shortcuts import HttpResponse
from app01 import models

def user_list(request):
    # result = models.UserInfo.objects.all().prefetch_related()
    # 加不加外鍵都是同樣的結果
    result = models.UserInfo.objects.all().prefetch_related('ut_id')
    """
    print(result.query)
    SELECT `app01_userinfo`.`id`, `app01_userinfo`.`name`, `app01_userinfo`.`age`, `app01_userinfo`.`ut_id` 
    FROM `app01_userinfo`
    """
    return HttpResponse()
12. 原生sql

ORM可以解決絕大多數查詢,但是可能解決不了非常複雜的請求。這個時候只能使用原生sql了,Django中使用原生sql的方式:

from django.shortcuts import HttpResponse
from app01 import models
from django.db import connection, connections

def user_list(request):
    try:
        # cursor = connection.cursor()  # connections['default'].cursor()
        cursor = connections['mysql'].cursor()
        cursor.execute("""select *from app01_userinfo where id >= 2 and id <= 4""")
        # row = cursor.fetchone()#(2, 'Thanlon', 23, 1)
        row = cursor.fetchall()  # (((2, 'Thanlon', 33, 1), (3, 'Kiku', 36, 2), (4, 'lili', 33, 1))
        print(row)
    except Exception as e:
        print(e)
    return HttpResponse()

settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'mysql': {
		'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_test',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章