Django ORM-01

What is ORM Django ?

ORM概念

對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種爲了解決面向對象與關係數據庫存在的互不匹配的現象的技術。mysql

簡單的說,ORM是經過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關係數據庫中。git

ORM在業務邏輯層和數據庫層之間充當了橋樑的做用。程序員

ORM由來

讓咱們從O/R開始。字母O起源於"對象"(Object),而R則來自於"關係"(Relational)。sql

幾乎全部的軟件開發過程當中都會涉及到對象和關係數據庫。在用戶層面和業務邏輯層面,咱們是面向對象的。當對象的信息發生變化的時候,咱們就須要把對象的信息保存在關係數據庫中。數據庫

按照以前的方式來進行開發就會出現程序員會在本身的業務邏輯代碼中夾雜不少SQL語句用來增長、讀取、修改、刪除相關數據,而這些代碼一般都是重複的。django

ORM的優點

ORM解決的主要問題是對象和關係的映射。它一般把一個類和一個表一一對應,類的每一個實例對應表中的一條記錄,類的每一個屬性對應表中的每一個字段。後端

ORM提供了對數據庫的映射,不用直接編寫SQL代碼,只需像操做對象同樣從數據庫操做數據。app

讓軟件開發人員專一於業務邏輯的處理,提升了開發效率。工具

ORM的劣勢

ORM的缺點是會在必定程度上犧牲程序的執行效率。code

ORM用多了SQL語句就不會寫了,關係數據庫相關技能退化...

ORM總結

ORM只是一種工具,工具確實能解決一些重複,簡單的勞動。這是不能否認的。

但咱們不能期望某個工具能一勞永逸地解決全部問題,一些特殊問題仍是須要特殊處理的。

可是在整個軟件開發過程當中須要特殊處理的狀況應該都是不多的,不然所謂的工具也就失去了它存在的意義。

django 中使用 ORM

在Django項目的settings.py文件中,配置數據庫鏈接信息

# 連接數據庫mysql
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "你的數據庫名稱",  # 須要本身手動建立數據庫
        "USER": "數據庫用戶名",
        "PASSWORD": "數據庫密碼",
        "HOST": "數據庫IP",
        "POST": 3306
    }
}
  • 特別注意的是用mysql init 文件要添加這句話
import pymysql
pymysql.install_as_MySQLdb()

Model 模型

在Django中model是你數據的單1、明確的信息來源。它包含了你存儲的數據的重要字段和行爲。一般,一個模型(model)映射到一個數據庫表.

基本狀況

  • 每一個模型都是一個Python類,它是django.db.models.Model的子類。
  • 模型的每一個屬性都表明一個數據庫字段。
  • 綜上所述,Django爲您提供了一個自動生成的數據庫訪問API

image

快速入門

下面這個例子定義了一個 Person 模型,包含 first_name 和 last_name。

from django.db import models
class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

first_name 和 last_name 是模型的字段。每一個字段被指定爲一個類屬性,每一個屬性映射到一個數據庫列。

sql

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);
  • 表myapp_person的名稱是自動生成的,若是你要自定義表名,須要在model的Meta類中指定 db_table 參數,強烈建議使用小寫表名,特別是使用MySQL做爲後端數據庫時

  • id字段是自動添加的,若是你想要指定自定義主鍵,只需在其中一個字段中指定 primary_key=True 便可。若是Django發現你已經明確地設置了Field.primary_key,它將不會添加自動ID列。

  • 本示例中的CREATE TABLE SQL使用PostgreSQL語法進行格式化,但值得注意的是,Django會根據配置文件中指定的數據庫後端類型來生成相應的SQL語句。

  • Django支持MySQL5.5及更高版本

AutoField:自增字段
  • int自增列,必須填入參數 primary_key=True。當model中若是沒有自增列,則自動會建立一個列名爲id的列。
IntegerField:整數字段
  • 一個整數類型,範圍在 -2147483648 to 2147483647。
CharField:字符字段
  • 字符類型,必須提供max_length參數, max_length表示字符長度。
DateField:日期字段
  • 日期字段,日期格式 YYYY-MM-DD,至關於Python中的datetime.date()實例。
DateTimeField:日期時間字段
  • 日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime()實例。

Foreign key:外鍵字段,通常用於一對多或則多對一,同時外鍵通常健在多的那一邊。

ManyToManyField:用於關聯兩張表,通常是多對多,將兩張表關聯起來

==那麼多對多的建立咱們又有三種方式:ManyToManyField==
  1. 使用ManyToManyField() --> ORM自動幫我建立第三張表,這種方式藉助ORM幫咱們建立一個第三張表。

image

  1. 手動建立第三張表:咱們直接在數據庫本身手動建立第三張表。

image

  1. 手動建立第三張表並設置ManyToManyField(),指定
books = models.ManyToManyField(
to="Book",
through="Book2Author",
through_fields=('author', 'book')
)

4 因此字段合集

AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 0 ~ 32767
    IntegerField(Field)
        - 整數列(有符號的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須爲逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          容許文件
                allow_folders=False,       容許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型

5.自定義字段

class FixedCharField(models.Field):
    """
    自定義的char類型的字段類
    """
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)

    def db_type(self, connection):
        """
        限定生成數據庫表的字段類型爲char,長度爲max_length指定的值
        """
        return 'char(%s)' % self.max_length


class Class(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=25)
    # 使用自定義的char類型的字段
    cname = FixedCharField(max_length=25)
6. 字段參數
null
用於表示某個字段能夠爲空。

unique
若是設置爲unique=True 則該字段在此表中必須是惟一的 。

db_index
若是db_index=True 則表明着爲此字段設置索引。

default
爲該字段設置默認值。
7. DateField和DateTimeField
auto_now_add
配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。

auto_now
配置上auto_now=True,每次更新數據記錄的時候會更新該字段。

image

8 . Foreign key OnetoOneFeild ManytoManyField
關係字段
ForeignKey

外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。

ForeignKey能夠和其餘表作關聯關係同時也能夠和自身作關聯關係。

字段參數
to
設置要關聯的表

to_field
設置要關聯的表的字段

related_name
反向操做時,使用的字段名,用於代替原反向查詢時的'表名_set'。

例如:

class Classes(models.Model):
    name = models.CharField(max_length=32)

class Student(models.Model):
    name = models.CharField(max_length=32)
    theclass = models.ForeignKey(to="Classes")


當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫:

models.Classes.objects.first().student_set.all()
當咱們在ForeignKey字段中添加了參數 related_name 後,

class Student(models.Model):
    name = models.CharField(max_length=32)
    theclass = models.ForeignKey(to="Classes", related_name="students")
當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫:

models.Classes.objects.first().students.all()
related_query_name
反向查詢操做時,使用的鏈接前綴,用於替換表名。

on_delete
當刪除關聯表中的數據時,當前表與其關聯的行的行爲。

models.CASCADE
刪除關聯數據,與之關聯也刪除


models.DO_NOTHING
刪除關聯數據,引起錯誤IntegrityError


models.PROTECT
刪除關聯數據,引起錯誤ProtectedError


models.SET_NULL
刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空)


models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值)


models.SET

刪除關聯數據,
a. 與之關聯的值設置爲指定值,設置:models.SET(值)
b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)


def func():
    return 10

class MyModel(models.Model):
    user = models.ForeignKey(
        to="User",
        to_field="id",
        on_delete=models.SET(func)
    )

db_constraint
是否在數據庫中建立外鍵約束,默認爲True。

OneToOneField
一對一字段。

一般一對一字段用來擴展已有字段。

字段參數
to
設置要關聯的表。

to_field
設置要關聯的字段。

on_delete
同ForeignKey字段。

ManyToManyField
用於表示多對多的關聯關係。在數據庫中經過第三張表來創建關聯關係。

字段參數
to
設置要關聯的表

related_name
同ForeignKey字段。

related_query_name
同ForeignKey字段。

symmetrical
僅用於多對多自關聯時,指定內部是否建立反向操做的字段。默認爲True。

舉個例子:

class Person(models.Model):
    name = models.CharField(max_length=16)
    friends = models.ManyToManyField("self")
此時,person對象就沒有person_set屬性。

class Person(models.Model):
    name = models.CharField(max_length=16)
    friends = models.ManyToManyField("self", symmetrical=False)
此時,person對象如今就可使用person_set屬性進行反向查詢。

through
在使用ManyToManyField字段時,Django將自動生成一張表來管理多對多的關聯關係。

但咱們也能夠手動建立第三張表來管理多對多關係,此時就須要經過through來指定第三張表的表名。

through_fields
設置關聯的字段。

db_table
默認建立第三張表時,數據庫中表的名稱。
8.元信息
db_table
ORM在數據庫中的表名默認是 app_類名,能夠經過db_table能夠重寫表名。

index_together
聯合索引。

unique_together
聯合惟一索引。

ordering
  • 指定默認按什麼字段排序。只有設置了該屬性,咱們查詢到的結果才能夠被reverse()

2.關於Django中的ORM操做必知必會十三條

<1> all():                 查詢全部結果
 
<2> filter(**kwargs):      它包含了與所給篩選條件相匹配的對象
 
<3> get(**kwargs):         返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
 
<4> exclude(**kwargs):     它包含了與所給篩選條件不匹配的對象
 
<5> values(*field):        返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列
 
<6> values_list(*field):   它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
 
<7> order_by(*field):      對查詢結果排序
 
<8> reverse():             對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。
 
<9> distinct():            從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
 
<10> count():              返回數據庫中匹配查詢(QuerySet)的對象數量。
 
<11> first():              返回第一條記錄
 
<12> last():               返回最後一條記錄
 
<13> exists():             若是QuerySet包含數據,就返回True,不然返回False

3. Django ORM query_demo

#ret = models.Book.objects.all()  # QuerySet類型  --> 書籍對象的列表
    print(ret)

    # ret = models.Book.objects.filter(title="圍城")  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # ret = models.Book.objects.filter(id=1)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # id值大於1
    # ret = models.Book.objects.filter(id__gt=1)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # id值小於3
    # ret = models.Book.objects.filter(id__lt=3)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # 出版日期是2017年的書
    # ret = models.Book.objects.filter(publisher_date__year=2017)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # 出版日期大於2017年
    # ret = models.Book.objects.filter(publisher_date__year__gt=2017)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)
    # 書名中包含'曌'的書
    # ret = models.Book.objects.filter(title__contains="曌")  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # 書名中包含'曌'的書而且出版年份是2018年
    # ret = models.Book.objects.filter(title__contains="曌", publisher_date__year=2018)  # QuerySet類型  --> 書籍對象的列表
    # print(ret)

    # get方法 若是檢索條件找不到對象就報錯
    # ret = models.Book.objects.get(id=10)  # 具體的類對象實例  --> 書籍對象
    # print(ret)

    # 使用filter檢索的時候沒有知足條件的數據就返回一個空 QuerySet
    # ret = models.Book.objects.filter(id=10)  # 具體的類對象實例  --> 書籍對象
    # print(ret)

    # 將知足條件的去掉,留下不知足條件的
    # ret = models.Book.objects.exclude(id__in=[1,3,4])
    # print(ret)

    # values 取字段的值
    # ret = models.Book.objects.filter(publisher_date__year=2018).values("title", "publisher_date")
    #  QuerySet類型  --> 字段及字段值的字典的列表
    # <QuerySet [{'id': 2, 'title': '牧羊少年奇幻漂流', 'price': 50}, {'id': 3, 'title': '一我的的朝聖', 'price': 40}]>
    # print(ret)
    #
    # ret = models.Book.objects.filter(publisher_date__year=2018).values_list("title", "publisher_date")
    #  QuerySet類型  --> 字段值的元祖的列表
    #結果爲:<QuerySet [(2, '牧羊少年奇幻漂流', 50), (3, '一我的的朝聖', 40)]>
    # print(ret)

    # 按字段排序
    # ret = models.Book.objects.all().order_by("price")  # QuerySet類型  --> 根據price字段對全部數據排序
    # print(ret)
    #
    # ret = models.Book.objects.all().order_by("-price")  # QuerySet類型  --> 根據price字段對全部數據排序
    # print(ret)
    #
    # ret = models.Book.objects.all().order_by("price").reverse()  # QuerySet類型  --> 根據price字段對全部數據排序
    # print(ret)
    #
    # # 按照出版時間排序
    # ret = models.Book.objects.all().order_by("publisher_date").reverse().values("title")  # QuerySet類型  --> 根據price字段對全部數據排序
    # print(ret)

    # 連表查詢
    # ret = models.Book.objects.all().values("publisher__name").distinct()  # QuerySet類型  --> 根據price字段對全部數據排序
    # print(ret)


    # count 計數
    # ret = models.Book.objects.all().count()  # 數字  --> 結果集中數據的個數
    # print(ret)

    # first()和last()
    # ret = models.Book.objects.all().first()  # 對象  --> 結果集中的第一個數據
    # print(ret)

    # 判斷結果集中是否有數據
    # ret = models.Book.objects.all().exists()  # 布爾值  --> 結果集中是否有數據
    # print(ret)
4.按照返回值分類
返回QuerySet對象的方法有
all()

filter()

exclude()

order_by()

reverse()

distinct()

特殊的QuerySet
values()       返回一個可迭代的字典序列

values_list() 返回一個可迭代的元祖序列

返回具體對象的
get()

first()

last()

返回布爾值的方法有:
exists()

返回數字的方法有
count()
5.單表查詢中雙下劃線
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值
 
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 
models.Tb1.objects.filter(name__contains="ven")  # 獲取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
 
models.Tb1.objects.filter(id__range=[1, 3])      # id範圍是1到3的,等價於SQL的bettwen and
 
相似的還有:startswith,istartswith, endswith, iendswith 

date字段還能夠:
models.Class.objects.filter(first_day__year=2017)
相關文章
相關標籤/搜索