django模型系統(二)
本文轉載自https://blog.csdn.net/xiaogeldx/article/details/87927345
常用的模型字段類型
模型的類對應的是數據庫中的表,模型的類屬性對應表的字段
Field的常用參數
- 參考文檔:https://docs.djangoproject.com/en/2.1/ref/models/fields/#field-options
- primary_key:指定是否為主鍵,通常不用自己定義,django會自動創建
- unique:指定是否唯一
- null:指定是否為空,默認為False
- blank:等於True時form表單驗證時可以為空,默認為False
- default:設置默認值
- DateField.auto_now:每次修改都會將當前時間更新進去
DateField.auto_now_add:第一次添加進去,都會將當前時間設置進去,以後修改,不會修改這個值
常用的字段類型
- 參考文檔:https://docs.djangoproject.com/en/2.1/ref/models/fields/#field-types
- IntegerField:整型,映射到數據庫中的int類型
- CharField:字符類型,映射到數據庫中的varchar類型,通過max_length指定最大長度
- Auto_Field:自動遞增的整數字段,通常不會用(因為通常不自定義主鍵)
- TextField:文本類型,映射到數據庫中的longtext類型
- BooleanField:布爾類型,映射到數據庫中的tinyint類型,在使用的時候,傳遞True/False進去,如果要可以為空,則用NullBooleanField
- DateField:日期類型,沒有時間,映射到數據庫中是date類型,在使用的時候可以設置DateField.auto_now每次保存對象時,自動設置該字段為當前時間,設置DateField.auto_now_add當對象第一次被創建時自動設置當前時間
DateTimeField:日期時間類型,映射到數據庫中的是datetime類型,在使用的時候,傳遞datetime.datetime()進去
常用的字段類型映射
int--------------------------IntegetField
varchar----------------------CharField
longtext----------------------TextField
datetime--------------DateTimeField常用查詢
- 通過模型類上的管理器(Student.objects)來構造QuerySet
- QuerySet表示數據庫中對象的集合,等同於MySQL中的select語句,惰性的
- 獲取單個對象
- first()獲取第一條數據,返回對象
- last()獲取最後一條數據,返回對象
- get(**kwargs)根據給定的條件,獲取一個對象,如果有多個對象符合或者沒有對象符合,會報錯,返回對象
- 獲取QuerySet
- all()獲取所有記錄,返回的是QuerySet
filter(**kwargs)根據給定的條件,獲取符合條件的過濾後的QuerySet,多個條件時使用and連接
In [19]: res = Student.objects.filter(age=17,sex=0) #選出age=17 and sex=0的數據 In [21]: res Out[21]: <QuerySet [<Student: na-17>]>
exclude(**kwargs)根據給定的條件,獲取不符合條件的過濾後的QuerySet,和filter使用方法一致,作用剛好相反,它是排除
In [24]: res = Student.objects.exclude(sex=0,age=16) #除了age=16 and sex=0的數據,剩下的都要 In [25]: res Out[25]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]> #因為沒有符合條件的數據,所以都取
多條件的or連接,用到Q對象,django.db.models.Q
In [27]: from django.db.models import Q In [28]: Student.objects.filter(Q(sex=0)|Q(sex=1)) #獲取性別是男或者是女 Out[28]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]> #所有數據都符合
values(*fields)指定字段(可以多個字段),返回一個QuerySet(QuerySet裏是字典列表,而不是數據對象),後面還可以加n個filter()
In [34]: res = Student.objects.values('name','sex').filter(age=17) In [35]: res Out[35]: <QuerySet [{'name': 'na', 'sex': 0}]> In [36]: res = Student.objects.values('name','age').filter(age=17).filter(sex=0) In [37]: res Out[37]: <QuerySet [{'name': 'na', 'age': 17}]>
- all()獲取所有記錄,返回的是QuerySet
- only(*)返回QuerySet(裏面是對象列表),一定包含主鍵字段,only用的比較多,可以指定很少的字段,高效
In [38]: res = Student.objects.only('name','age').filter(sex=0)
In [39]: res
Out[39]: <QuerySet [<Student: na-17>, <Student: di-18>]>
In [40]: print(res.query)
SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age` FROM `students_student` WHERE `students_student`.`sex` = 0 #主鍵id
In [41]: res = Student.objects.only('name','age').filter(sex=0).filter(name='di')
In [42]: res
Out[42]: <QuerySet [<Student: di-18>]>
In [43]: res[0].c_time
Out[43]: datetime.datetime(2019, 2, 26, 0, 27, 28, 626041, tzinfo=<UTC>)
defer(*fields)返回一個QuerySet,和only用法一樣,作用相反,fields是指定排除的字段
In [44]: res = Student.objects.defer('c_time','age') In [46]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`e_time` FROM `students_student`
order_by(*fields)根據給定字段來排序
In [47]: res = Student.objects.order_by('c_time').only('name') In [48]: res Out[48]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]> In [49]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name` FROM `students_student` ORDER BY `students_student`.`c_time` ASC
order_by(*-fields)根據給定字段來倒序(和正序唯一區別是在字段名前加個負號)
In [52]: res = Student.objects.order_by('-c_time').only('name') In [53]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name` FROM `students_student` ORDER BY `students_student`.`c_time` DESC In [54]: res Out[54]: <QuerySet [<Student: di-18>, <Student: long-19>, <Student: na-17>, <Student: xiaoge-16>]>
切片,和Python列表切片用法相似,不支持負索引,數據量大時不用步長
切片後不再支持附加過濾條件與排序In [55]: res = Student.objects.all()[:2] In [56]: res Out[56]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>]> In [57]: res = Student.objects.all()[2:3] In [58]: res Out[58]: <QuerySet [<Student: long-19>]> In [59]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time`, `students_student`.`e_time` FROM `students_student` LIMIT 1 OFFSET 2 In [60]: res = Student.objects.all()[1:3] In [61]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time`, `students_student`.`e_time` FROM `students_student` LIMIT 2 OFFSET 1 *offset偏移坐標,偏移的位置 In [62]: res = Student.objects.all()[::1] In [63]: res Out[63]: [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]
常用查詢條件
- 支持filter,exclude,get
exact準確匹配(__exact)
In [65]: res = Student.objects.filter(id__exact=13) In [66]: res Out[66]: <QuerySet [<Student: di-18>]>
iexact模糊匹配,不區分大小寫(__iexact)
In [67]: res = Student.objects.filter(name__iexact='XIAOGE') In [69]: res Out[69]: <QuerySet [<Student: xiaoge-16>]>
contains包含,在首尾亦可(__contains)
In [71]: res = Student.objects.filter(name__contains='ao') In [72]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time`, `students_student`.`e_time` FROM `students_student` WHERE `students_student`.`name` LIKE BINARY %ao% In [73]: res Out[73]: <QuerySet [<Student: xiaoge-16>]>
icontains不區分大小寫的包含(__icontains)
In [74]: res = Student.objects.filter(name__icontains='ON') In [75]: res Out[75]: <QuerySet [<Student: long-19>]>
in給定一個可叠代的對象(列表,元組,QuerySet)
In [76]: res = Student.objects.filter(name__in=['xiaoge','小哥','aaa']) In [77]: res Out[77]: <QuerySet [<Student: xiaoge-16>]> In [78]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time`, `students_student`.`e_time` FROM `students_student` WHERE `students_student`.`name` IN (xiaoge, 小哥, aaa)
range範圍
In [79]: res = Student.objects.filter(age__range=(16,19)) In [80]: res Out[80]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]> In [81]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`sex`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time`, `students_student`.`e_time` FROM `students_student` WHERE `students_student`.`age` BETWEEN 16 AND 19
gt大於,gte大於等於,lt小於,lte小於等於
In [82]: res = Student.objects.filter(age__gt=18) In [83]: res Out[83]: <QuerySet [<Student: long-19>]> In [84]: res = Student.objects.filter(age__gte=18) In [85]: res Out[85]: <QuerySet [<Student: long-19>, <Student: di-18>]> In [86]: res = Student.objects.filter(age__lte=18) In [87]: res Out[87]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: di-18>]> In [88]: res = Student.objects.filter(age__lt=18) In [89]: res Out[89]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>]>
- startswith以...開頭,大小寫敏感,istartswith,不區分大小寫
endswith以...結尾,區分大小寫,iendswith,不區分大小寫
In [90]: res = Student.objects.filter(name__startswith='xi') In [91]: res Out[91]: <QuerySet [<Student: xiaoge-16>]> In [92]: res = Student.objects.filter(name__endswith='na') In [93]: res Out[93]: <QuerySet [<Student: na-17>]> In [94]: res = Student.objects.filter(name__iendswith='NG') In [95]: res Out[95]: <QuerySet [<Student: long-19>]>
isnull,值為True或False,對應MySQL中的IS NULL和IS NOT NULL,判斷是否為空
In [97]: res = Student.objects.filter(name__isnull=True) In [98]: res Out[98]: <QuerySet []> In [99]: res = Student.objects.filter(name__isnull=False) In [100]: res Out[100]: <QuerySet [<Student: xiaoge-16>, <Student: na-17>, <Student: long-19>, <Student: di-18>]>
聚合與分組
聚合
- from django.db.models import Count,Avg,Max,Min,Sum
- 通過QuerySet的aggregate方法
count統計數量,Avg平均值,Max最大值,Min最小值,Sum求和
In [102]: Student.objects.all().count() Out[102]: 4 In [103]: Student.objects.filter(age__gt=16).count() Out[103]: 3 In [104]: from django.db.models import Avg,Count,Max,Min,Sum In [105]: Student.objects.aggregate(age_avg=Avg('age')) Out[105]: {'age_avg': 17.5} In [106]: Student.objects.filter(sex=1).aggregate(max_avg=Max('age')) Out[106]: {'max_avg': 19} In [107]: Student.objects.filter(sex=0).aggregate(age_min=Min('age')) Out[107]: {'age_min': 17} In [108]: Student.objects.filter(sex=0).aggregate(age_sum=Sum('age')) Out[108]: {'age_sum': 35}
分組,聚合
結合Values,annotate和聚合方法一起實現
#查詢男生女生分別是多少個 In [109]: Student.objects.values('sex').annotate(num=Count('sex')) Out[109]: <QuerySet [{'sex': 1, 'num': 2}, {'sex': 0, 'num': 2}]> In [110]: Student.objects.values('sex').annotate(Count('sex')) Out[110]: <QuerySet [{'sex': 1, 'sex__count': 2}, {'sex': 0, 'sex__count': 2}]>
django模型系統(二)