1. 程式人生 > 其它 >Django8-2.模型系統常用知識點(2)

Django8-2.模型系統常用知識點(2)

技術標籤:# 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中的型別說明
intIntegerField整型
varcahrCharField字元型別,通過max_length指定最大長度
longtxtTextField文字型別
dateDateField日期型別,沒有時間。對映到資料庫中是date型別,在使用的時候,可以設定DateField.auto_now每次儲存物件時,自動設定該欄位為當前時間
datetimeDateTimeField日期時間型別。對映到資料庫中的是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: 第一次新增進去,都會將當前時間設定進去。以後修改,不會修改這個值