零基礎入手Django(七):模型基礎2
今天,小叮當來為大家繼續(xù)分享Django干貨~

主要內容有:常用的查詢、常用字段類型及常用參數、表關系的實現
一、常用的查詢
常用的查詢方法總結
由于其使用方法在零基礎入手Django(六):模型基礎1中已經為大家介紹過,這里只挑選出來幾個具有代表性的進行演示。
(1)使用order_by逆向排序
重新定義查詢視圖函數
在瀏覽器中訪問

在Pycharm后臺端,查看輸出結果

可以看到,默認查詢是按id正序排列。使用order_by方法后,我們成功使得輸出按照age進行了逆向排列。
值得注意,在按age倒序輸出時,相同age的數據還是按id從小到大排列了,例如age=18時,先輸出了id=1的xdd才輸出了id=2的小叮當。
這時我們就可以使用order_by,對多個字段進行排序,使得當age相同時,便按id從大到小進行排序。
在視圖函數中添加如下語句:
print('我使用了多字段',ors)
在瀏覽器中訪問后,在后臺查看

(2)values將輸出結果字典化
重新定義查詢視圖函數
#查詢數據
def?search_user(request):
????rs?=?User.objects.all()
????print('我是默認查詢結果',rs)
????vrs?=?User.objects.all().values()
????print('我是字典化后的結果',vrs)???
????return?HttpResponse('我在使用values字典化查詢結果')
在瀏覽器中查看

在pycharm后臺端查看輸出結果

(3)count查詢數據總數
在查詢視圖函數中,添加如下代碼
print('數據總數為',num)
在瀏覽器中查看

在pycharm后臺端查看結果

2.常用的查詢條件總結
#1.等于號??exact
rs?=?User.objects.filter(name__exact='xiaodingdang')
#iexact是忽略了大小寫匹配的等于
#2.包含??contains
rs?=?User.objects.filter(name__contains='xiao')
#icontains是忽略了大小寫匹配的包含
#3.以什么開始??startswith
rs?=?User.objecsts.filter(name__startswith='xiao')
#istartswith是忽略了大小寫的startswith
#4.以什么結尾??endswith
rs?=?User.objects.filter(name__endswith='dang')
#iendswith是忽略了大小寫的endswith
#5.成員所屬?in
rs?=?User.objects.filter(age__in=[18,19,20])
#6.大于?gt
rs?=?User.objects.filter(age__gt=18)
#7.大于等于?gte
rs?=?User.objects.filter(age__gte=18)
#8.小于?lt
rs?=?User.objects.filter(age__lt=20)
#9.小于等于?lte
rs?=?User.objects.filter(age__lte=20)
#10.區(qū)間?range
rs?=?User.objects.filter(age__range=(18,20))
#11.判斷是否為空
rs?=?User.objects.filter(city__isnull=True)
定義查詢視圖函數
#查詢數據
def?search_user(request):
????ers?=?User.objects.filter(name__exact='小叮當')
????print('查詢name等于小叮當的數據',ers)
????crs?=?User.objects.filter(name__contains='x')
????print('查詢name包含了x的數據',crs)
????srs?=?User.objects.filter(name__startswith='神仙')
????print('查詢name以神仙開頭的數據',srs)
????endrs?=?User.objects.filter(name__endswith='叮當')
????print('查詢name以叮當結尾的數據',endrs)
????grs?=?User.objects.filter(age__gt=19)
????print('查詢age大于19的數據',grs)
????lrs?=?User.objects.filter(age__lt=19)
????print('查詢age小于19的數據',lrs)
????rrs?=?User.objects.filter(age__range=(18,19))
????print('查詢age在[18,19)的數據',rrs)
????irs?=?User.objects.filter(age__in=[18,19])
????print('查詢age為18和19的數據',irs)
????nrs?=User.objects.filter(city__isnull=True)
????print('判斷city字段是否為空',nrs)
????return?HttpResponse('我在使用條件查詢數據')
在瀏覽器中訪問

在后臺查看結果

其中值得注意的是,在django中使用條件查詢時,相當于使用了sql語句中的where。其語法是:字段名__規(guī)則?(字段名和規(guī)則之間是兩條下劃線)
例如:
就相當于sql語句
select * from .... where city is null
二、常用字段類型及常用參數
常用的字段類型映射關系
在models.py中我們可以看到,我們只使用了AutoField(自增長類型)、CharField(字符類型)、IntegerField(整數類型)等數據類型。

其實,在Django中還有其它幾種常用的字段類型,它們的映射關系如下

常用的字段類型總結如下:
1.IntegerField:整型,映射到數據庫中的int類型。
2.CharField:字符類型,映射到數據庫中的varchar類型,通過max_length指定最大長度。
3.TextField:文本類型,映射到數據庫中的text類型。
4.BooleanField:布爾類型,
映射到數據庫中的tinyint類型,在使用的時候
傳遞True/False進去。如果要可以為空,則用NullBooleanField。
5.DateField:日期類型,沒有時間。
映射到數據庫中是date類型。在使用的時候,
可以設置DateField.auto_now每次保存對象時,自動設置該字段為當前時間。
設置DateField.auto_now_add當對象第一次被創(chuàng)建時自動設置當前時間。
6.DateTimeField:日期時間類型,
映射到數據庫中的是datetime類型。
在使用的時候,傳遞datetime.datetime()進去。
Field的常用參數總結如下:
1.primary_key:指定是否為主鍵。
2.unique:指定是否唯一。
3.null:指定是否為空,默認為False。
4.blank:等于True時form表單驗證時可以為空,默認為False。
5.default:設置默認值。
6.DateField.auto_now:每次修改都會將當前時間更新進去,只有調用
QuerySet.update方法將不會更新,這個參數只是Date和DateTime以及
TimModel.save()方法才會調用e類才有的。
DateField.auto_now_add:第一次添加進去,都會將當前時間設置進去,
以后修改,不會修改這個值。
2.使用常用類型創(chuàng)建數據表
(1)我們在models.py中新建Field_Test模型類作為一張新的表
? ? name = models.CharField(max_length=30,unique=True)
? ? age = models.IntegerField()
? ? note = models.TextField()
? ? gender = models.BooleanField(default=True)
? ? create_time = models.DateField(auto_now_add=True)#第一次存入數據的時間
? ? update_time = models.DateTimeField(auto_now=True)#每次更新就會修改
(2)在pycharm的tools中找到"Run manage.py Task..."

執(zhí)行makemigrations?model_test

(3)執(zhí)行migrate model_test

(4)使用xshell進行查看
執(zhí)行命令“mysql -u xdd(用戶名) -p(輸入密碼)”

執(zhí)行命令“use mydb;"

執(zhí)行命令”show tables;“

執(zhí)行命令”desc model_test_field_test;"

3.向表中插入數據
(1)重新定義添加數據的視圖函數
from?.models?import?Field_Test
def?add_user(request):
??Field_Test.objects.create(name='小叮當',age=17,
note='我是小叮當',gender=False)
??return?HttpResponse('小叮當在向field_test中添加數據!')
(2)在瀏覽器中訪問

(3)通過xshell進行查看

4.更新數據
(1)重新定義添加數據的視圖函數
def?add_user(request):
??rs?=?Field_Test.objects.get(id=1)
??rs.name?=?"快樂小叮當"
??rs.save()
??return?HttpResponse('小叮當在更新數據!')
(2)在瀏覽器中訪問

(3)通過xshell查看

可以看到,數據更新的時間已經自動更新。但是顯示的更新的時間與我們真實的時間相差了8個小時~大家知道這是時區(qū)默認設置導致的即可。
值得注意,只有使用.save()方法更新數據,系統才會自動更新時間。而使用update方法更新,則不會調用auto_now自動更新時間。
三、表關系的實現
1.表關系示意圖

2.示例
為了明確在django中如何創(chuàng)建豐富的表關系,小叮當為大家示例如下
(1)表關系圖
假如有下面這幾張表

它們的關系可以這樣表示:

(2)在項目中新建app,并注冊
在項目中新建名為db_test的app用來實現表關系。在Tools中打開Run manage.py Task...

執(zhí)行命令“startapp?db_test"

在項目處,右鍵將創(chuàng)建好的app下載下來

在項目的settings文件中注冊創(chuàng)建好的app

(3)創(chuàng)建表
我們在建好的”db_test“的models.py中創(chuàng)建表。值得注意,當出現一對多,多對多,一對一等復雜關系時,我們一般先從”一“這一端來創(chuàng)建表。
在models.py中創(chuàng)建模型類如下:
#1.創(chuàng)建學院信息表
class?Department(models.Model):
??????d_id?=?models.AutoField(primary_key=True)
??????d_name?=?models.CharField(max_length=30)
#2.創(chuàng)建學生信息表
class?Student(models.Model):
????s_id?=?models.AutoField(primary_key=True)
????s_name?=?models.CharField(max_length=30)
????#實現一對多關系ForeignKey?其中on_delete為必填字段使用級聯刪除CASCADE
????department?=?models.ForeignKey('Department',on_delete=models.CASCADE)
#3.課程信息表
class?Course(models.Model):
????c_id?=?models.AutoField(primary_key=True)
????c_name?=?models.CharField(max_length=30)
????#實現多對多關系?ManyToManyField
????student?=?models.ManyToManyField('Student')
#4.學生詳細信息表
class?Stu_detail(models.Model):
????#?實現一對一關系OneToOneField?其中on_delete為必填字段使用級聯刪除CASCADE
??????student?=?models.OneToOneField('Student',on_delete=models.CASCADE)
??????age?=?models.IntegerField()
??????gender?=?models.BooleanField(default=1)
??????city?=?models.CharField(max_length=30,null=True)
在Pycharm的Tools中打開Run manage.py Task...
執(zhí)行?makemigrations

執(zhí)行?migrate

在xshell?的mysql中?執(zhí)行 show tables;

執(zhí)行?desc db_test_department;?查看學院信息表

執(zhí)行?desc db_test_student;??查看學生信息表

可以看到,學生信息表中自動為我們關聯生成了”department_id"外鍵,也就是department表的d_id
關于級聯刪除:
只有引用的數據全部刪除后,才可以刪除被引用表中的父類數據。例如,學院信息表中1代表計算機學院。在學生信息表中,小明、小紅、小花都是計算機學院,他們的外鍵值都是1,想要在學院信息表中刪除計算機學院,需要在學生信息表中先刪除了引用計算機學院的小明、?小紅、小花。
執(zhí)行?desc db_test_course;?查看課程表

執(zhí)行?desc db_test_stu_detail;?查看學生詳細信息表

可以看到,已經按照我們的設置,學生詳細信息表和學生表建立了一對一的關系。
再次執(zhí)行,show tables;

我們看到,我們已實現了學生表與課程表的多對多關系,系統已為我們自動生成了中間信息表“db_test_course_student"。
執(zhí)行?desc db_test_course_student;?進行查看,結果如下
