Django8-2.模型系統常用知識點(2)
阿新 • • 發佈:2021-01-20
技術標籤:# Django知識點pythonmysql資料庫django
Django——Molde模組
文章目錄
本篇接上文,在查詢之前,我們將Model進行再次升級,使得更加完善:
Student/models.py
from django.db import models
# Create your models here.
class Student(models.Model):
name = models.CharField(max_length=20) # 對應於mysql的varchar
age = models.SmallIntegerField(null=True) # 對應於mysql的smallint
sex = models.SmallIntegerField(default=1) # default是預設值
qq = models.CharField(max_length=20, null=True, unique=True) # qq和電話雖然是數字,但是我們儲存一般使用字串去儲存
phone = models.CharField(max_length=20, null=True, unique=True)
# c_time = models.DateTimeField(verbose_name="建立時間", auto_now_add=True) # verbose_name用來給該欄位新增說明 auto_now_add=True自動填充當前時間)
c_time = models.DateTimeField("建立時間", auto_now_add=True) # 當然你想完全可以在第一個引數寫入名字而省略寫verbose_name這個引數名
x_time = models.DateTimeField("修改時間", auto_now=True) # 修改之後自動儲存
def __str__(self):
return "這個學生的名字是:%s,年齡為:%d" % (self.name, self.age)
接下來就是遷移的兩步(確定遷移資料,和執行遷移),檢視以下我們的資料表:
mysql> desc Student_student;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | smallint | YES | | NULL | |
| sex | smallint | NO | | NULL | |
| qq | varchar(20) | YES | UNI | NULL | |
| phone | varchar(20) | YES | UNI | NULL | |
| c_time | datetime(6) | NO | | NULL | |
| x_time | datetime(6) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
此時我們是沒有資料的,我們可以新增進入一些資料:
In [1]: from Student.models import Student
In [2]: Student.objects.create(name="summer", age=20, sex=1, qq="12345678", phone="87654321")
Out[2]: <Student: 這個學生的名字是:summer,年齡為:20>
In [3]: Student.objects.create(name="Summer", age=20, sex=1, qq="123", phone="456")
Out[3]: <Student: 這個學生的名字是:Summer,年齡為:20>
In [4]: Student.objects.create(name="July", age=20, sex=1, qq="1234", phone="567")
Out[4]: <Student: 這個學生的名字是:July,年齡為:20>
In [5]: Student.objects.create(name="April", age=20, sex=1, qq="1212", phone="11567")
Out[5]: <Student: 這個學生的名字是:April,年齡為:20>
In [6]: Student.objects.create(name="馬冬梅", age=40, sex=0, qq="6666", phone="7777")
Out[6]: <Student: 這個學生的名字是:馬冬梅,年齡為:40>
In [7]: Student.objects.create(name="Moli", age=18, sex=0, qq="5678", phone="71212")
Out[7]: <Student: 這個學生的名字是:Moli,年齡為:18>
六、查詢拓展
1. 常用查詢方法
1-1 查詢所有(all)
In [9]: Student.objects.all()
Out[9]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, <0>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
1-2 filter查詢
In [10]: Student.objects.filter(name="summer")
Out[10]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>]>
In [11]: res = Student.objects.filter(name="summer")
In [12]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`name` = summer
1-3 get查詢
In [14]: Student.objects.get(name="moli")
Out[14]: <Student: 這個學生的名字是:Moli,年齡為:18>
注意:get所查詢的值必須是唯一的,如果沒有或者多個將會報錯
以上三個共同點
都是通過objects去實現的----》objects:每個django模型類,都有一個預設的管理器,objects
1-4 查詢第一條(first)
In [1]: from Student.models import Student as S # 重新進入,為了方便將Student模型進行重新命名
In [2]: S.objects.first()
Out[2]: <Student: 這個學生的名字是:summer,年齡為:20> # 並且檢視到這個方法返回的是一個物件而並不是一個queryset
1-5 查詢最後一條(last)
In [3]: S.objects.last()
Out[3]: <Student: 這個學生的名字是:Moli,年齡為:18>
1-6 排除查詢(exclude)
為了方便,我們與filter進行比較
In [4]: S.objects.filter(name="april")
Out[4]: <QuerySet [<Student: 這個學生的名字是:April,年齡為:20>]>
In [5]: S.objects.exclude(name="april")
Out[5]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, <0>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
我們看到,exclude正好與filter相反,filter是獲取這個值,而exclude是排除這個值
1-7 指定欄位查詢(values)
In [9]: S.objects.values("name")
Out[9]: <QuerySet [{'name': 'summer'}, {'name': 'Summer'}, {'name': 'July'}, {'name': 'April'}, {'name': '馬冬梅'}, {'name': 'Moli'}]>
注意:values能拿到指定查詢的欄位值,其他的無法獲取
In [1]: from Student.models import Student as S
In [2]: res = S.objects.values("name")
In [3]: res
Out[3]: <QuerySet [{'name': 'summer'}, {'name': 'Summer'}, {'name': 'July'}, {'name': 'April'}, {'name': '馬冬梅'}, {'e': 'Moli'}]>
In [4]: res[0]["name"]
Out[4]: 'summer'
In [5]: res[0]["sex"]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-5-1ed973621d80> in <module>
----> 1 res[0]["sex"]
KeyError: 'sex'
In [6]: print(res.query)
SELECT `Student_student`.`name` FROM `Student_student`
1-8 指定欄位查詢2 (only)
In [7]: res = S.objects.only("name")
In [8]: res
Out[8]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, <Student: 這個學生的名字是:July,年齡為:20>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
In [9]: res[0]["name"]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-27a2df2438b0> in <module>
----> 1 res[0]["name"]
TypeError: 'Student' object is not subscriptable
In [10]: res[1].name
Out[10]: 'Summer'
In [11]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name` FROM `Student_student`
注:這裡返回的物件是一個queryset,因此不能在使用字典的方式獲取,得用.
。並且這個是可以拿到其他值的。
1-9 指定欄位查詢3(defer)
In [14]: res = S.objects.defer("name")
In [15]: res
Out[15]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, 20>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
In [16]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student`
注:defer與only剛好相反
1-10 指定欄位排序(order_by)
In [17]: res = S.objects.order_by('age')
In [18]: res
Out[18]: <QuerySet [<Student: 這個學生的名字是:Moli,年齡為:18>, <Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, <Student: 這個學生的名字是:July,年齡為:20>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>]>
In [19]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` ORDER BY `Student_student`.`age` ASC
In [20]: res = S.objects.order_by('-age')
In [21]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` ORDER BY `Student_student`.`age` DESC
注:寫入的值預設為正序,如果想要倒敘直接在前面加-
即可
1-11 多條件查詢
此時,你需要匯入一個包from django.db.models import Q
In [27]: S.objects.filter(age=20,sex=0)
Out[27]: <QuerySet []>
In [28]: S.objects.filter(age=20,sex=1)
Out[28]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, 20>, <Student: 這個學生的名字是:April,年齡為:20>]>
In [29]: from django.db.models import Q
In [30]: S.objects.filter(Q(sex=0),Q(age=20)|Q(age=18))
Out[30]: <QuerySet [<Student: 這個學生的名字是:Moli,年齡為:18>]>
2. 常用查詢條件
查詢物件的條件的意思是傳給以上方法的一些引數。相當於是SQL語句中的where語句後面的條件,語法為欄位名__規則(是連著兩個下劃線哦)
2-1 exact和iexact
In [31]: res = S.objects.filter(name__exact="summer")
In [32]: res
Out[32]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>]>
In [33]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`name` = summer
In [34]: res = S.objects.filter(name="summer")
In [35]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`name` = summer
In [36]: res = S.objects.filter(name__iexact="summer")
In [37]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`name` LIKE summer
In [38]: res
Out[38]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>]>
原生sql裡面我們發現,exact和”=“是相同的,而iexact將where語句中的=變成了like
mysql> select * from Student_student where name="summer";
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
| id | name | age | sex | qq | phone | c_time | x_time |
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
| 5 | summer | 20 | 1 | 12345678 | 87654321 | 2021-01-19 04:19:52.965210 | 2021-01-19 04:19:52.965279 |
| 6 | Summer | 20 | 1 | 123 | 456 | 2021-01-19 04:20:13.082947 | 2021-01-19 04:20:13.082981 |
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
2 rows in set (0.01 sec)
mysql> select * from Student_student where name like "summer";
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
| id | name | age | sex | qq | phone | c_time | x_time |
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
| 5 | summer | 20 | 1 | 12345678 | 87654321 | 2021-01-19 04:19:52.965210 | 2021-01-19 04:19:52.965279 |
| 6 | Summer | 20 | 1 | 123 | 456 | 2021-01-19 04:20:13.082947 | 2021-01-19 04:20:13.082981 |
+----+--------+------+-----+----------+----------+----------------------------+----------------------------+
2 rows in set (0.00 sec)
2-2 包含匹配(contains)
查詢包含某個引數的值
In [39]: res = S.objects.filter(name__contains="l")
In [40]: res
Out[40]: <QuerySet [<Student: 這個學生的名字是:July,年齡為:20>, <Student: 這個學生的名字是:April,年齡為:20>, <St]>
In [41]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`name` LIKE BINARY %l%
In [42]: res = S.objects.filter(name__contains="S")
In [43]: res
Out[43]: <QuerySet [<Student: 這個學生的名字是:Summer,年齡為:20>]>
注:上面的是對大小寫敏感的,如果要不銘感則需要加一個i
In [44]: res = S.objects.filter(name__icontains="S")
In [45]: res
Out[45]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>]>
2-3 指定值(in)
In [46]: S.objects.filter(pk__in=[4,5,6])
Out[46]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>]>
In [47]: S.objects.filter(sex__in="01")
Out[47]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, 20>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
這裡你可以指定字串也可以指定列表和元組
2-4 子查詢(icontains)
In [50]: res = S.objects.filter(name__icontains="l").only("name")
In [51]: res
Out[51]: <QuerySet [<Student: 這個學生的名字是:July,年齡為:20>, <Student: 這個學生的名字是:April,年齡為:20>, <St]>
In [52]: res1 = S.objects.filter(pk__in=res).only("name")
In [53]: print(res1.query)
SELECT `Student_student`.`id`, `Student_student`.`name` FROM `Student_student` WHERE `Student_student`.`id` IN (SELECT U0.`id` FROM `Student_student` U0 WHERE U0.`name` LIKE %l%)
2-5 範圍查詢
- gt 大於
- gte 大於等於
- lt 小於
- lte 小於等於
- range
In [54]: S.objects.filter(pk__gt=5)
Out[54]: <QuerySet [<Student: 這個學生的名字是:Summer,年齡為:20>, <Student: 這個學生的名字是:July,年齡為:20>, <S0>, <Student: 這個學生的名字是:馬冬梅,年齡為:40>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
In [58]: res = S.objects.filter(age__range=(10,20))
In [59]: res
Out[59]: <QuerySet [<Student: 這個學生的名字是:summer,年齡為:20>, <Student: 這個學生的名字是:Summer,年齡為:20>, 20>, <Student: 這個學生的名字是:April,年齡為:20>, <Student: 這個學生的名字是:Moli,年齡為:18>]>
In [60]: print(res.query)
SELECT `Student_student`.`id`, `Student_student`.`name`, `Student_student`.`age`, `Student_student`.`sex`, `Student_student`.`qq`, `Student_student`.`phone`, `Student_student`.`c_time`, `Student_student`.`x_time` FROM `Student_student` WHERE `Student_student`.`age` BETWEEN 10 AND 20
2-6 聚合分組查詢(annotate)
同樣需要匯入:from django.db.models import Count,Avg,Max,Min,Sum
In [63]: from django.db.models import Count,Avg,Max,Min,Sum
In [64]: res = S.objects.values("sex").annotate(num=Count("sex"))
In [65]: res
Out[65]: <QuerySet [{'sex': 1, 'num': 4}, {'sex': 0, 'num': 2}]>
In [66]: print(res.query)
SELECT `Student_student`.`sex`, COUNT(`Student_student`.`sex`) AS `num` FROM `Student_student` GROUP BY `Student_student`.`sex` ORDER BY NULL
七、常用模型欄位型別
1.常用的欄位型別對映關係
Mysql中的型別 | Model中的型別 | 說明 |
---|---|---|
int | IntegerField | 整型 |
varcahr | CharField | 字元型別,通過max_length指定最大長度 |
longtxt | TextField | 文字型別 |
date | DateField | 日期型別,沒有時間。對映到資料庫中是date型別,在使用的時候,可以設定DateField.auto_now每次儲存物件時,自動設定該欄位為當前時間 |
datetime | DateTimeField | 日期時間型別。對映到資料庫中的是datetime型別,在使用的時候,傳遞datetime.datetime()進去。 |
八、Field的常用引數
- primary_key: 指定是否為主鍵。
- unique: 指定是否唯一。
- null: 指定是否為空,預設為False。
- blank: 等於True時form表單驗證時可以為空,預設為False。
- default: 設定預設值。
- DateField.auto_now: 每次修改都會將當前時間更新進去,只有呼叫,QuerySet.update方法將不會呼叫。這個引數只是Date和DateTime以及TimModel.save()方法才會呼叫e類才有的。
- DateField.auto_now_add: 第一次新增進去,都會將當前時間設定進去。以後修改,不會修改這個值