2-django的模型

2-django的模型

概述:Django對各類數據庫都提供了很好的支持,Django爲這些數據庫提供了統一的調用接口API,程序員能夠根據本身的業務需求選擇不一樣的數據庫html

ORM簡介

概述:對象-關係-映射python

做用: 根據類生成表結構;將對象、列表的操做轉換成對應的SQL語句;將SQL語句查詢到的結果轉換爲對象或者列表 git

優勢:極大的減輕開發人員的工做量,不須要面對因數據庫的變動而致使代碼無效在修改代碼, 防止sql注入攻擊程序員

圖解:sql

clipboard.png定義模型數據庫

模型、屬性、表、字段之間的關係:一個模型在數據庫中對應一張表,在模型中定義的屬性對應該模型對照表中的一個字段django

建立模型類

班級類segmentfault

class Grade(models.Model):
    name     = models.CharField(max_length=20)
    boyNum   = models.IntegerField()
    girlNum  = models.IntegerField()
    isDelete = models.BooleanField(default=False)
    def __str__(self):
        return self.name

學生類函數

class Student(models.Model):
    name     = models.CharField(max_length=20)
    sex      = models.BooleanField()
    age      = models.IntegerField()
    contend = models.CharField(max_length=40)
    #  關聯類名的小寫或直接類名 Grade
    grade    = models.ForeignKey("grade")
    isDelete = models.BooleanField(default=False)
    def __str__(self):
        return self.name

字段類型和字段選項

字段類型        
        ·AutoField
            ·一個根據實際ID自動增加的IntegerField,一般不指定若是不指定,一個主鍵字段將自動添加到模型中

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

        ·TextField
            ·大文本字段,通常超過4000使用,默認的表單控件是Textarea

        ·IntegerField
            ·整數

        ·DecimalField(max_digits=None, decimal_places=None)
            ·使用python的Decimal實例表示的十進制浮點數
            ·參數說明
                ·DecimalField.max_digits
                    ·位數總數
                ·DecimalField.decimal_places
                    ·小數點後的數字位數

        ·FloatField
            ·用Python的float實例來表示的浮點數

        ·BooleanField
            ·true/false 字段,此字段的默認表單控制是CheckboxInput

        ·NullBooleanField
            ·支持null、true、false三種值

        ·DateField(auto_now=False, auto_now_add=False)
            ·使用Python的datetime.date實例表示的日期
            ·參數說明
                ·DateField.auto_now
                    ·每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,                        默認爲false
                ·DateField.auto_now_add
                    ·當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false
            ·說明
                ·該字段默認對應的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日曆控件,和一                    個「Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
            ·注意
                ·auto_now_add, auto_now, and default 這些設置是相互排斥的,他們之間的任何組合會發生錯誤的結果

        ·TimeField
            ·使用Python的datetime.time實例表示的時間,參數同DateField

        ·DateTimeField
            ·使用Python的datetime.datetime實例表示的日期和時間,參數同DateField

        ·FileField
            ·一個上傳文件的字段

        ·ImageField
            ·繼承了FileField的全部屬性和方法,但對上傳的對象進行校驗,確保它是個有效的image
字段選項
        ·概述
            ·經過字段選項,能夠實現對字段的約束
            ·在字段對象時經過關鍵字參數指定

        ·null
            ·若是爲True,Django 將空值以NULL存儲到數據庫中,默認值是 False

        ·blank
            ·若是爲True,則該字段容許爲空白,默認值是 False

        ·注意
            ·null是數據庫範疇的概念,blank是表單驗證證範疇的

        ·db_column
            ·字段的名稱,若是未指定,則使用屬性的名稱

        ·db_index
            ·若值爲 True, 則在表中會爲此字段建立索引

        ·default
            ·默認值

        ·primary_key
            ·若爲 True, 則該字段會成爲模型的主鍵字段

        ·unique
            ·若是爲 True, 這個字段在表中必須有惟一值

模型之間的關係

模型關係
        ·分類
            ·ForeignKey:一對多,將字段定義在多的端中
            ·ManyToManyField:多對多,將字段定義在兩端中
            ·OneToOneField:一對一,將字段定義在任意一端中

        ·用一訪問多
            ·格式
                對象.模型類小寫_set
            ·示例
                grade.students_set

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

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

元選項

在模型類中定義一個Meta類,用於設置元信息spa

class Student(models.Model):
    name     = models.CharField(max_length=20)
    sex      = models.BooleanField()
    age      = models.IntegerField()
    contend = models.CharField(max_length=40)
    #                            關聯類名的小寫
    grade    = models.ForeignKey("grade")
    isDelete = models.BooleanField(default=False)
    def __str__(self):
        return self.name
    class Meta():
        db_table = "students"
        ordering = ["-id"]

屬性

  • db_table: 定義數據表名,推薦使用類名小寫,而且添加複數
  • ordering: 規定對象的默認排序字段 ; ordering = ["id"]: 正序; ordering = ["-id"]: 倒序;

注意:排序會增長數據庫的開銷

模型成員

objects對象

概述: 是Manager類型的對象,用於與數據庫進行交互; 當定義模型時沒有指定管理器,則Django會爲模型提供一個名爲objects的管理器

自定義模型管理器

class Student(models.Model):
    #自定義模型管理器
    myobject = models.Manager()
    
    name     = models.CharField(max_length=20)
    sex      = models.BooleanField()
    age      = models.IntegerField()
    contend = models.CharField(max_length=40)
    #                            關聯類名的小寫
    grade    = models.ForeignKey("grade")
    isDelete = models.BooleanField(default=False)
    def __str__(self):
        return self.name
    class Meta():
        db_table = "students"
        ordering = ["-id"]

注意: 若是爲模型指定了管理器,那麼Django再也不爲模型類提供名爲objects的管理器

自定義模型管理器類

class StudentManager(models.Manager):
    def get_queryset(self):
        return super(StudentManager, self).get_queryset().filter(isDelete=False)
class Student(models.Model):
    #自定義模型管理器
    objects = StudentManager()

get_queryset獲取查詢集(數據集),自定義管理器類調用父類中的get_queryset方法後在進行過濾

建立對象

當建立對象時,Django不會對數據庫進行讀寫操做。調用save()方法才與數據庫進行交互,將對象存儲到數據庫中。__init__方法已經在基類models.Model中使用,在自定義模型類中沒法使用

在模型類中增長一個類方法:

class Student(models.Model):
    #自定義模型管理器
    objects = StudentManager()

    name     = models.CharField(max_length=20)
    sex      = models.BooleanField()
    age      = models.IntegerField()
    contend = models.CharField(max_length=40)                        
    grade    = models.ForeignKey(Grade)
    isDelete = models.BooleanField(default=False)
    def __str__(self):
        return self.name
    class Meta():
        db_table = "students"
        ordering = ["-id"]
   
    #類方法,類能夠直接調用  建立對象能夠直接寫 Student.create('ray',1,18,....)
    @classmethod 
    def create(cls, name, sex, age, contend, grade):
        return cls(name=name, sex=sex, age=age, contend=contend, grade=grade)

在自定義模型器類中增長一個方法

class StudentManager(models.Manager):
    def get_queryset(self):
        return super(StudentManager, self).get_queryset().filter(isDelete=False)
    def create(self, name, sex, age, contend, grade):
        obj = self.model()
        obj.name = name
        obj.sex = sex
        obj.age = age
        obj.contend = contend
        obj.grade = grade
        return obj

查詢數據

查詢集:表示從數據庫中獲取的對象集合,查詢集能夠含有一個或者多個過濾器

過濾器:基於所給的參數限制查詢集的結果,獲得新的查詢集

從SQL的角度,查詢集合select語句等價,過濾器就像where和limit子句類似

查詢集

在管理器上調用過濾器方法或者是其餘數據查詢集上調用過濾器方法獲得新的查詢集

查詢集通過過濾器篩選獲得新的查詢集,所以可使用鏈式語法結構

惰性查詢:建立查詢集不會帶來任何的數據庫訪問,直到調用數據時,纔會訪問數據庫

何時對查詢集求值? 迭代、序列化、與if合用

返回查詢集的方法

all()

返回查詢集的方法

def students(request):
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

filter()

做用:將符合條件的數據過濾進來

使用:filter(鍵1=值1, 鍵2=值2);filter(鍵1=值1, 鍵2=值2)

def students(request):
    stus = Student.objects.filter(age=20)
    return render(request, 'students.html', {"stus":stus})

exclude()

做用: 將符合條件的數據過濾出去

def students(request):
    stus = Student.objects.exclude(age=20)
    return render(request, 'students.html', {"stus":stus})

order_by()

做用:排序

def students(request):
    stus = Student.objects.order_by("age")
    return render(request, 'students.html', {"stus":stus})
def students(request):
    stus = Student.objects.order_by("-age")
    return render(request, 'students.html', {"stus":stus})

values()

做用: 一個對象構成一個字典,而後構成一個列表返回

def students(request):
    stus = Student.objects.values()
    print(stus)
    return render(request, 'students.html', {"stus":stus})

返回單個值的方法

get()

做用: 返回單個知足條件的對象

def students(request):
    #   pk表明主鍵
    try:
        stus = [Student.objects.get(age=20)]
    except Student.DoesNotExist as e:
        pass
    except Student.MultipleObjectsReturned as e:
        pass
    return render(request, 'students.html', {"stus":stus})

注意: 若是多條數據被返回,會引起 「類名.MultipleObjectsReturned」 異常;數據不存在會報 "類名.DoesNotExist" 異常

count()

返回當前查詢的總條數

first()

返回查詢集中的第一個對象

last()

返回查詢集中的最後一個對象

exists()

判斷查詢集中是否有數據,若是有返回True,不然返回False

def students(request):
    stus = Student.objects.filter(age=20)
    if stus.exists():
        return render(request, 'students.html', {"stus":stus})
    else:
        return HttpResponse("沒有學生數據")

限制查詢集

查詢集返回列表,可使用下標的方式進行限制,等同於SQL中的limit和offset子句

注意: 不支持負數索引; 使用下標後返回一個新的查詢集,不會當即執行查詢字段查詢

def students(request):
    stus = Student.objects.all()[5:10]#[0:5)
    return render(request, 'students.html', {"stus":stus})

字段查詢

概述

實現where語句,做爲filter()、exclude()、get()的參數

語法 : 屬性名稱__比較運算符=值 (注意:裏面有兩個下劃線)

外鍵: 使用 「屬性名_id」 表示原始的外鍵值

轉義: like語句中使用%,能夠直接使用

比較運算符

exact: 表示判斷至關,大小寫敏感

contains: 是否包含,大小寫敏感

# 找描述中帶有"ray"的全部學生
def students(request):
    stus = Student.objects.filter(contend__icontains="sunck")
    return render(request, 'students.html', {"stus":stus})

startswith、endswith: 以value開頭、結尾,大小寫敏感

# 找描述以ray開頭的全部學生
def students(request):
    stus = Student.objects.filter(contend__startswith="ray")
    return render(request, 'students.html', {"stus":stus})

iexact、icontains、istartswith、iendswith: 不區分大小寫

isnull, isnotnull : 是否爲空, 是否爲非空

in : 包含在範圍以內

# 找id爲2,5,8,9的學生
def students(request):
    stus = Student.objects.filter(pk__in=[2,5,8,9])
    return render(request, 'students.html', {"stus":stus})

gt, gte, lt, lte

# 找年齡大於等於20的全部學生
def students(request):
    stus = Student.objects.filter(age__gte=20)
    return render(request, 'students.html', {"stus":stus})

year、month、day、week_day、hour、minute、second: 對日期類型的屬性進行運算

跨關聯關係的查詢

處理join查詢:

語法:關聯的模型類名小寫__屬性名__比較運算符=值

注意: __比較運算符 沒有,表示等於; 能夠反向使用,即關聯的兩個模型中均可以使用

# 描述中帶有ray的學生屬於那些班級
def students(request):
    grades = Grade.objects.filter(student__contend__contains="ray")
    print(grades)
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

查詢的快捷方式: pk pk表示主鍵,默認主鍵是id

聚合函數

注意: 使用aggregate()函數返回聚合函數的值

函數: Avg、Count、Max、Min、Sum

# 求全部人的年齡的和
from django.db.models import Sum
def students(request):
    age = Student.objects.aggregate(Sum("age"))
    print("***********", age)
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

F對象

做用: 可使模型中的A字段與B字段進行比較,若是A字段出如今等號的左側,那麼B字段使用F對象寫在等號右側

# 找男生個數多於女生個數的班級
from django.db.models import F
def students(request):
    grades = Grade.objects.filter(boyNum__gt=F("girlNum"))
    print(grades)
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

F對象能夠進行數學運算

from django.db.models import F
def students(request):
    grades = Grade.objects.filter(boyNum__gt=F("girlNum")*2)
    print(grades)
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

F對象還能夠進行關聯查詢 模型類小寫__屬性名

# 沒有被刪除的學生的班級
from django.db.models import F
def students(request):
    grades = Grade.objects.filter(isDelete=F("student__isDelete"))
    print(grades)
    stus = Student.objects.all()
    return render(request, 'students.html', {"stus":stus})

對於data/time字段,能夠進行timedelta()進行運算

Q對象

邏輯與

# 年齡大於等於20且小於等於50的學生
def students(request):
    stus = Student.objects.filter(age__gte=20,age__lte=50)
    return render(request, 'students.html', {"stus":stus})
def students(request):
    stus = Student.objects.filter(age__gte=20).filter(age__lte=50)
    return render(request, 'students.html', {"stus":stus})

from django.db.models import Q
def students(request):
    stus = Student.objects.filter(Q(age__gte=20) & Q(age__lte=50))
    return render(request, 'students.html', {"stus":stus})

邏輯或

# 獲取年齡小於20或者年齡大於50的學生
from django.db.models import Q
def students(request):
    stus = Student.objects.filter(Q(age__lt=20) | Q(age__gt=50))
    return render(request, 'students.html', {"stus":stus})

邏輯非

# 獲取年齡不大於等於20的學生
def students(request):
    stus = Student.objects.filter(age__lt=20)
    return render(request, 'students.html', {"stus":stus})

from django.db.models import Q
def students(request):
    stus = Student.objects.filter(~Q(age__gte=20))
    return render(request, 'students.html', {"stus":stus})

注意: 過濾器函數中能夠混合使用Q對象和關鍵字參數,全部參數條件都將and在一塊兒,Q對象必須位於關鍵字參數的前面

def students(request):
    stus = Student.objects.all()[5:10]#[0:5)
    return render(request, 'students.html', {"stus":stus})

模型關係

1-1

使用場景: 表的字段太多,須要拆分

# 人
class Person(models.Model):
    name = models.CharField(max_length=20)
    age  = models.IntegerField()
    # 關係存放在哪張表均可以
    # 綁定身份證與人的一對一關係,默認狀況下當刪身份證時綁定的人也能夠刪除,經過on_delete屬性設置
    idCard = models.OneToOneField(IDCard)
# 身份證
class IDCard(models.Model):
    sex = models.BooleanField()
    num = models.CharField(max_length=20)

主表從表: 聲明關係的表爲從表

級聯數據獲取:

從獲取主:

  • 關係是直接聲明的,是一個顯性的屬性
  • 獲取pk爲1的人的身份證號
  • per = Person.objects.get(pk=1) print(per.idCard.num)

主獲取從:

  • 關係字段是隱性屬性,對象.關係模型類名的小寫
  • 獲取身份證號是1的人的姓名
  • card = IDCard.objects.get(pk=1) print(card.person.name)

img

1-n

一對多,也就是外鍵。

主表從表: 聲明關係的表爲從表(ForeignKey)。

級聯數據獲取:

  • 從獲取主: 關係是直接聲明的,是一個顯性的屬性
  • 主獲取從: 關係字段是隱性屬性,對象.模型類小寫_set
#找到1班的全部學生
grade = Grade.objects.get(pk=1)
print(grade.student_set.all())

m-n

原理: 底層是經過兩個外鍵實現,兩個外鍵存在於另外一張關係表中

#多對多
class Buyer(models.Model):
    name = models.CharField(max_length=20)
    level = models.IntegerField()
class Product(models.Model):
    name = models.CharField(max_length=20)
    price = models.IntegerField()
    #關係造成
    buyers = models.ManyToManyField(Buyer)

造成關係

def ptob(reqeust, p, b):
    product = Product.objects.get(pk=p)
    buyer   = Buyer.objects.get(pk=b)
    #產生關聯
    product.buyers.add(buyer)
    return HttpResponse("購買成功")

數據級聯獲取

從獲取主

  • 對象.顯性屬性,獲得的是一個數據集合,能夠進行過濾
  • 已知一件商品,獲取該商品全部的購買者
  • product = Product.objects.get(pk=1) print(product.buyers.all())

主獲取從:

  • 隱性屬性 對象.關聯類名小寫_set 獲得的是一個數據集合,能夠進行過濾
  • 已知一個購買者,獲取他所買的全部商品
  • buyer = Buyer.objects.get(pk=1) print(buyer.product_set.all())

模型繼承

使用最原始的python類的繼承方式

class Animal(models.Model):
    name = models.CharField(max_length=20)
    age  = models.IntegerField()
class Cat(Animal):
    weight = models.IntegerField()
class Dog(Animal):
    height = models.IntegerField()

注意: 默認繼承方式不是很合理

  • 父類也會對應一張表
  • 默認在父類中定義的字段會存在父類表中,子類的數據經過外鍵關聯父表中數據,子類只有特殊的數據在子表中
  • 效率比較低

Django中的數據庫模塊提供了一個很是不錯的功能,就是支持models的面向對象,能夠在Meta類中指定是否抽象,而後繼承

class Animal(models.Model):
    name = models.CharField(max_length=20)
    age  = models.IntegerField()
    class Meta():
        # 讓該類抽象,抽象的父類不會再生產數據表
        # 子類會繼承父類中的通用數據,複製到子表中
        abstract = True
class Cat(Animal):
    weight = models.IntegerField()
class Dog(Animal):
    height = models.IntegerField()
相關文章
相關標籤/搜索