Django - 02-Django模型

[toc]

1 模型

Django對各種數(shù)據(jù)庫都提供了很好的支持,Django為這些數(shù)據(jù)庫提供了統(tǒng)一的調(diào)用API,可以根據(jù)不同的業(yè)務(wù)需求,選擇不同的數(shù)據(jù)庫;

1.1 開發(fā)流程

配置數(shù)據(jù)庫:
        python3.x 安裝的是PyMySQL; python2.x 安裝的是mysql-python
        
        在工程目錄下的__init__.py寫入兩行代碼
                import pymysql
                pymysql.install_as_MySQLdb()
            
        配置 settings.py
                DATABASES = {
                    'default': {
                        'ENGINE': 'django.db.backends.mysql',
                        'NAME': 'class',
                        'USER': 'root',
                        'PASSWORD': 'admin',
                        'HOST': '192.168.23.128',
                        'PORT': '3306',
                    }
                }


定義模型類
        一個模型類都在數(shù)據(jù)庫中隊形一張數(shù)據(jù)表;

生成遷移文件

執(zhí)行遷移

使用模型類進行增、刪、改、查

1.2 ORM

1.2.1 概述

對象-關(guān)系-映射

1.2.2 任務(wù)

  • 根據(jù)對象類型生成表結(jié)構(gòu);
  • 將對象、列表的操作轉(zhuǎn)換為SQL語句;
  • 將SQL語句查詢到的結(jié)果轉(zhuǎn)換為對象、列表;

1.2.3 優(yōu)點

  • 極大的減輕了開發(fā)人員的工作量,不需要面對因數(shù)據(jù)庫的改變而修改代碼;

1.2.4 圖解

graph TD
    A[Django] 
    B[ORM]
    C1[MySQL]
    C2[sqlite]
    C3[Oracle]

1.3 定義模型

1.3.1 模型、屬性、表、字段間的關(guān)系

  • 一個模型類在數(shù)據(jù)庫中對應(yīng)一張表;
  • 在模型類中定義的屬性,對應(yīng)該模型對照表中的一個字段;

1.3.2 定義屬性

1. 概述

  • Django根據(jù)屬性的類型確定以下信息:
    • 當前選擇的數(shù)據(jù)庫支持字段的類型;
    • 渲染管理表單時使用的默認html控件;
    • 在管理站點最低限度的驗證;
  • Django會為表增加自動增長的主鍵列;
    每個模型只能有一個主鍵列;
    如果使用選項設(shè)置某屬性為主鍵列后,則Django不會再生成默認的主鍵列;
  • 屬性命名限制:
    • 遵循標識符規(guī)則
    • 不能是python的保留關(guān)鍵字;
    • 由于Django的查詢方式,不允許使用連續(xù)的下劃線;

2. 庫

  • 定義屬性時,需要字段類型,字段類型被定義在 django.db.models.fields 目錄下;
    為了方便使用,被導(dǎo)入到 django.db.models 中;
  • 使用方式:
    • 導(dǎo)入: from django.db import models
    • 通過 models.Field 創(chuàng)建字段類型的對象,賦值給屬性;

3. 邏輯刪除

  • 對于重要數(shù)據(jù)都做邏輯刪除,不做物理刪除;
    實現(xiàn)方法是定義 isDelete 屬性,類型為 BooleanFiled,默認值為 False;

4. 字段類型

字段類型(字段選項)

AutoField
        一個根據(jù)實際 ID 自動增長的 IntegerField,通常不指定;
        如果不指定,一個主鍵字段將自動添加到模型中;

CharField(max_length=字符長度)
        字符串,默認表單樣式是 TextInput;

TextField
        大文本字段,一般超過4000字節(jié)使用,默認表單控件是 Textarea;

IntegerField
        整數(shù)類型;

DecimaField(max_digits=None, decimal_places=None)
        使用 python 的Decimal 實例表示的十進制浮點數(shù);
        參數(shù)說明:
                DecimalField.max_digits
                    位數(shù)總數(shù)
                DecimalField.decimal_places
                    小數(shù)點后的數(shù)字位數(shù)

FloatField
        用 python 的 float 實例來表示的浮點數(shù);


BooleanField
        True/False 字段,此字段的默認表單控制是 CheckboxInput;

NullBooleanField
        支持Null、True、False三種值;

DateField(auto_now=False, auto_now_add=False)
        使用 python 的 datetime.date 實例表示日期;
        參數(shù)說明:
                DateField.auto_now
                    每次保存對象時,自動設(shè)置該字段為當前時間,用于“最后一次修改”的時間戳,它總是使用當前日期,默認為 False;
                DateField.auto_now_add
                    當對象第一次被創(chuàng)建時自動設(shè)置當前時間,用于創(chuàng)建的時間戳,它總是使用當前日期,默認為 False;
        說明:
                該字段默認對應(yīng)的表單控件是一個 TextInput;<br>在管理員站點添加了一個 JavaScrtpt 寫的日歷控件,和一個“Today”的快捷按鈕;<br>包含了一個額外的 invalid_date 錯誤消息鍵;
        注意:
                auto_now、auto_now_add、default 這些設(shè)置是相互排斥的,他們之間的任何組合都將會發(fā)生錯誤的結(jié)果;

TimeField
        使用 python 的 datetime.time 實例表示的時間,參數(shù)同 DateField;

DateTimeField
        使用 python 的 datetime.datetime 實例表示的日期和時間,參數(shù)同 DateField;


FileField
        一個上傳文件的字段;


ImageField
        繼承了 FileField 的所有屬性和方法,但對上傳的對象進行校驗,確保它是個有效的 image;

5. 字段選項

字段類型(字段選項)

概述:
        通過字段選項,可以實現(xiàn)對字段的約束;
        在字段對象時,通過關(guān)鍵字參數(shù)指定;

null
        null = True     一般不寫
        如果為 True,Django 將空值以 NULL 存儲到數(shù)據(jù)庫中,默認值是 False;

blank
        如果為 True,則該字段允許為空白,默認值是 False;

注意:null 是數(shù)據(jù)庫范疇的概念;blank 是表單驗證范疇的概念;


db_column
        sage = models.IntegerField(db_column='age')     指定這個字段再數(shù)據(jù)庫中名字是age 
        字段的名稱,如果未指定,則使用屬性的名稱;

db_index
        若值為 True,則在表中會為此字段創(chuàng)建索引;

default
        默認值

primary_key
        若為True,則該字段會成為模型的主鍵字段;
        
unique
        如果為True,則該字段再表中必須有唯一值;

6. 關(guān)系

分類:
        Foreignkey:一對多,將字段定義在多的端中
                Grades 和 Students 是一對多關(guān)系,F(xiàn)oreignkey定義在Students中;
        ManyToManyField:多對多,將字段定義在兩端中;
        OneToOneField:一對一,將字段定義在任意一端中;
        
        
用一訪問多:
        格式: 對象.模型類小寫_set
        示例: grade.student_set

用一訪問一:
        格式: 對象.模型類小寫
        示例: grade.student

訪問id:
        格式: 對象.屬性_id
        示例: student.sgrade_id

1.3.3 創(chuàng)建模型類

1.3.4 元選項

在模型類中定義Meta類,用于設(shè)置元信息;

        class Grade(models.Molde):
            class Meat:
                db_table='students'     # 定義數(shù)據(jù)表名,推薦使用小寫字母,數(shù)據(jù)表名默認為:項目名小寫_類名小寫
                ordering=['id']           # 對象的默認排序字段,獲取對象的列表時使用
                        ordering=['id]      # 按id字段升序排列
                        ordering=['-id']    # 按id字段降序排列
                        注意: 排序會增加數(shù)據(jù)庫開銷

    
示例:
        class Student(models.Model):
            sname = models.CharField(max_length=20)
            sgender = models.BooleanField(default=True)
            sage = models.IntegerField()
            scontend = models.TextField()
            isDelete = models.BooleanField(default=False)
            sgrade = models.ForeignKey('Grade')
        
            def __str__(self):
                return self.sname
            
            lasttime = models.DateTimeField(auto_now=True)
            createtime = models.DateTimeField(auto_now_add=True)
            
            class Meta:
                db_table = 'student'
                ordering = ['id']

1.4 模型成員

1.4.1 類屬性

objects
        是Manager類型的一個對象,作用是與數(shù)據(jù)庫進行交互;
        當定義模型類時,沒有指定管理器,那么Django為模型創(chuàng)建一個名為objects的管理器;
        
        
自定義管理器:
        class Student(models.Model):
            # 自定義模型管理器
            stuObj = models.Manager()
        
        stu = Student.stuObj.get(pk=1)
        
        當為模型指定模型管理器,Django就不在為模型類生成objects模型管理器;
        
        
自定義管理器Manager類:
        模型管理器是Django的模型進行與數(shù)據(jù)庫進行交互的接口;一個模型類可以有多個模型管理器;
                stuObj = models.Manager()
                stuObj1 = models.Manager()
                
        作用:
                向管理器類中添加額外的方法
                修改管理器返回的原始查詢集      重寫get_queryset()方法
                
        示例: 查詢Student表中 isDelete=Flase的內(nèi)容
                class StudentManager(models.Manager):
                    def get_queryset(self):
                        return super(StudentManager, self).get_queryset().filter(isDelete=False)
                
                class Student(models.Model):
                    # 自定義模型管理器
                    stuObj = models.Manager()
                    stuObj2 = StudentManager()

1.4.2 創(chuàng)建對象

目的:
        項數(shù)據(jù)庫添加數(shù)據(jù)
        
當創(chuàng)建對象時,Django不會對數(shù)據(jù)庫進行讀寫操作;
當調(diào)用save時,才與數(shù)據(jù)庫有交互,將對象保存到數(shù)據(jù)庫中;

注意:
        __init__() 方法已經(jīng)在父類models.Model中使用,在自定義的模型中無法使用;
        
方法:
        1. 在模型類中增加一個類方法;
                class Student(models.Model):
                    # @classmethod 表明是類方法
                    @classmethod
                    def createStudents(cls, name, gender, age, contend, isD=False):
                        stu = cls(sname = name,
                                    sgender = gender,
                                    sage = age,
                                    scontend = contend,
                                    isDelete=isD)
                        return stu
            #-------------------------------------------------------------------------------
                # views.py
                def addStudent(request):
                    grade = Grade.objects.get(pk=1)
                    stu = Student.createStudents("劉德華", True, 34, '我叫劉德華', grade)
                    stu.save()
                    return HttpResponse('Yeah')
            #-------------------------------------------------------------------------------
                # urls.py
                url(r'^addstudent/$', views.addStudent),
                        
        2. 在自定義管理器中添加一個方法
                class StudentManager(models.Manager):
                    def createStudent(self, name, gender, age, contend, grade, isD=False):
                        stu = self.model()
                        stu.sname = name
                        stu.sgrade = gender
                        stu.sage = age
                        stu.scontend = contend
                        stu.sgrade = grade  
                        return stu

1.4.3 模型查詢

概述:
        查詢集表示從數(shù)據(jù)庫獲取的對象的集合;
        查詢集可以有多個過濾器;
        過濾器就是一個函數(shù),基于所給的參數(shù)限制查詢集結(jié)果;
        從SQL角度來說,查詢集和select語句等價,過濾器等同于 SQL 的 where 條件;
        

查詢集:
        在管理器調(diào)用過濾器方法,返回查詢集;
        查詢集經(jīng)過過濾器篩選后,返回新的查詢集,所以可以寫成鏈式調(diào)用;
        
        惰性執(zhí)行:
                創(chuàng)建查詢集不會帶來任何數(shù)據(jù)庫的訪問,直到調(diào)用數(shù)據(jù)時們才會訪問數(shù)據(jù);
            
        直接訪問數(shù)據(jù)的情況:
                迭代
                序列化
                與if合用
                
        返回查詢集的方法稱為過濾器:
                all()           返回查詢集中所有的數(shù)據(jù)的對象;
                
                filter()
                        返回符合條件的數(shù)據(jù);
                        filter(鍵=值, 鍵=值)
                        filter(鍵=值).filter(鍵=值)
                        
                exclude()       過濾掉符合條件的數(shù)據(jù)
                
                order_by()      排序
                
                values()        以條數(shù)據(jù)就是一個字典,返回一個列表;
                
        返回單個數(shù)據(jù):
                get()
                        返回一個滿足條件的對象;
                        注意:
                                如果沒有找到符合條件的對象,會引發(fā) "模型類.DoesNotExist" 異常;
                                如果找到多個對象,會引發(fā) "模型類.MultipleObjectsReturned" 異常;
                count()     返回當前查詢集中的個數(shù);
                first()     返回當前查詢集中的第一個對象;
                last()      返回當前查詢集中的最后一個對象;
                exists()    判斷查詢集中是否有數(shù)據(jù),有則返回True;
                
        限制查詢集:
                查詢集返回列表,可以使用下標來進行限制,等同于 SQL 的 limit 語句;
                        def student3(request):
                            studentList = Student.stuObj.all()[0:3]
                            return render(request, 'myapp/student.html', {'student': studentList})
                
                注意:下標不能是負數(shù);
                
                需求:分頁顯示學生信息
                url.py
                    url(r'^stupage/(\d)/$', views.stupage),
                    
                views.py
                    def stupage(request, page):
                        # 0-3  3-6  6-9
                        #  1    2    3
                        page = int(page)
                        studentList = Student.stuObj.all()[(page-1)*3: (page*3)]
                        return render(request, 'myapp/student.html', {'student': studentList})
        
        查詢集的緩存:
                概述:
                        每個查詢集都包含一個緩存,來最小化對數(shù)據(jù)庫訪問;
                        在新建的查詢集中,緩存首次為空,第一次對查詢集求值,會發(fā)生數(shù)據(jù)緩存;
                        Django會將查詢的數(shù)據(jù)做一個緩存,并返回查詢結(jié)果,以后查詢直接使用查詢集的緩存;
        
        字段查詢:
                概述:
                        實現(xiàn)了 SQL 中的 where 語句,作為方法filter()、exclude()、get()的參數(shù)
                        語法:  
                                屬性名稱__比較運算符=值
                        外鍵:  
                                屬性名_id
                        轉(zhuǎn)義:  
                                like 語句使用%是為了匹配占位,匹配數(shù)據(jù)中的% (where like '\%')
                                filter(sanme_cotains='%')
                                
                比較運算符:
                        exact
                                判斷,大小寫敏感(區(qū)分大小寫)
                                filter(isDelete=False)
                        
                        contans
                                是否包含,大小寫敏感
                                studentList = Student.stuObj.all().filter(sname__contains='張')
                        
                        startswith、endswith
                                以value開頭或者結(jié)尾,大小寫敏感
                                studentList = Student.stuObj.all().filter(sname__startswith='張')
                        
                    以上四個在參數(shù)前加 i 就表示不區(qū)分大小寫:iexact、icontans、istartswith、iendswith
                    
                        isnull、isnotnull
                                是否為空
                            
                        in
                                是否包含在范圍內(nèi)
                                studentList = Student.stuObj.all().filter(pk__in=[2,4,6,8])
                        
                        gt      大于
                        gte     大于等于
                        lt      小于
                        lte     小于等于
                                studentList = Student.stuObj.all().filter(sage__gt=20)
                                
                        year
                        month
                        day
                        week_day
                        hour
                        minute
                        second
                                給datetime、date、time類型的字段使用
                                
                        跨關(guān)聯(lián)查詢
                                處理join查詢
                                        語法:
                                                模型類名__屬性名__比較運算符
                                                grade = Grade.objects.filter(student__scontend__contains='劉德華')
                                                print(grade)
                                                描述中帶有劉德華的班級的內(nèi)容
                        
                        查詢快捷
                                pk      代表主鍵
                    
                        
                聚合函數(shù):
                        使用aggregate()函數(shù)返回聚合函數(shù)的值;
                        Avg
                        Count
                        Max
                        Min
                        Sum
                                from django.db.models import Max
                                def studentSearch(request):
                                    maxAge = Student.stuObj.aggregate(Max('sage'))
            
                F對象
                        可以使用模型的 A屬性 與 B屬性 進行比較
                                from django.db.models import F
                                def grades(request):
                                    g = Grades.object.filter(ggirlnum__gt=F('gboynum'))
                                    print(g)
                                return HttpResponse('女生比男生數(shù)多的班')
                        支持F對象的算數(shù)運算
                                g = Grades.object.filter(ggirlnum__gt=F('gboynum')+10)
                        
                        支持F對象的時間的運算
                
                Q對象
                        概述:  過濾器的方法中的關(guān)鍵字參數(shù),條件為and模式
                        需求:  進行or查詢
                        解決:  使用Q對象
                                studentList = Student.stuObj2.filter(Q(pk__lt=5) | Q(sage__gt=20))
                                studentList = Student.stuObj2.filter(Q(pk__lt=5))       只有一個Q對象,就是用于匹配的;
                                studentList = Student.stuObj2.filter(~Q(pk__lt=5))      ~   取反

1.4.4 刪、改

刪
        對象名.del()
改
        對象名.save()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文:https://my.oschina.net/liuyuantao/blog/751438 查詢集API 參...
    陽光小鎮(zhèn)少爺閱讀 3,966評論 0 8
  • Django 1.8.2 文檔Home | Table of contents | Index | Modules...
    軒轅小愛閱讀 2,425評論 0 2
  • 文章內(nèi)容大部分參考官方文檔,以作者理解敘述Django中模型是你的數(shù)據(jù)的唯一的,確定的信息源.它包含你所存儲數(shù)據(jù)所...
    da_yu閱讀 2,135評論 0 3
  • Django 準備 “虛擬環(huán)境為什么需要虛擬環(huán)境:到目前位置,我們所有的第三方包安裝都是直接通過 pip inst...
    33jubi閱讀 1,394評論 0 5
  • 前言 根據(jù)前幾篇文章的分享已經(jīng)了解djangoWeb開發(fā)一般步驟為:創(chuàng)建虛擬環(huán)境安裝django創(chuàng)建項目創(chuàng)建應(yīng)用在...
    博行天下閱讀 1,219評論 0 2

友情鏈接更多精彩內(nèi)容