Django orm經常使用字段和字段參數

1.Object Relational Mapping(ORM)

1.1ORM介紹

ORM概念

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

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

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

ORM由來

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

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

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

ORM的優點

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

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

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

ORM的劣勢

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

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

ORM總結

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

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

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

1.2Django中的ORM

Django項目使用MySQL數據庫

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

 

複製代碼
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "你的數據庫名稱",  # 須要本身手動建立數據庫
        "USER": "數據庫用戶名",
        "PASSWORD": "數據庫密碼",
        "HOST": "數據庫IP",
        "POST": 3306
    }
}
複製代碼

 

2. 在Django項目的__init__.py文件中寫以下代碼,告訴Django使用pymysql模塊鏈接MySQL數據庫:

a) python2須要安裝mysql-python:

  pip install mysql-python

b) python3須要安裝pymysql:

 

import pymysql

pymysql.install_as_MySQLdb()

mysql命令回顧

登陸mysql數據庫:mysql –uroot –p

查看有哪些數據庫:show databases

建立數據庫:create database test2 charset=utf8; #切記:指定編碼

使用數據庫:use test2;

查看數據庫中的表:show tables;

Model

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

基本狀況:

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

 

 

快速入門

下面這個例子定義了一個 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 是模型的字段。每一個字段被指定爲一個類屬性,每一個屬性映射到一個數據庫列。

上面的 Person 模型將會像這樣建立一個數據庫表:

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及更高版本。

軟刪除標記:

刪除數據時不作真正的刪除,而是把標記數據設置爲1表示刪除,目的是防止重要的數據丟失

1.3 模型類生成表

1) 生成遷移文件

命令:python manage.py makemigrations

2) 執行遷移生成表

命令:python mange.py migrate

根據遷移文件生成表。

生成表名的默認格式:

應用名_模型類名小寫

1.4經過模型類操做數據表

進入項目shell的命令:

python manage.py shell

如下爲在相互shell終端中演示的例子:

首先導入模型類:

from booktest.models import BookInfo,HeroInfo

1) 向booktest_bookinfo表中插入一條數據。

b = BookInfo() #定義一個BookInfo類的對象

b.btitle ='天龍八部' #定義b對象的屬性並賦值

b.bpub_date = date(1990,10,11)

b.save() #纔會將數據保存進數據庫

2) 查詢出booktest_bookinfo表中id爲1的數據。

b = BookInfo.objects.get(id=1)

3) 在上一步的基礎上改變b對應圖書的出版日期。

b.bpub_date = date(1989,10,21)

b.save() #纔會更新表格中的數據

4) 緊接上一步,刪除b對應的圖書的數據。

b.delete() #纔會刪除

5) 向booktest_heroInfo表中插入一條數據。

h = HeroInfo()

h.hname = '郭靖'
h.hgender = False

h.hcomment = ‘降龍十八掌

b2 = BookInfo.objects.get(id=2)

h.hbook = b2  #給關係屬性賦值,英雄對象所屬的圖書對象

h.save()

6) 查詢圖書表裏面的全部內容。

BookInfo.objects.all()

HeroInfo.objects.all()

1.5後臺管理

1) 本地化

語言時區的本地化。

修改settings.py文件。

2) 建立管理員

命令:python manage.py createsuperuser

3) 註冊模型類

在應用下的admin.py中註冊模型類。

告訴djang框架根據註冊的模型類來生成對應表管理頁面。

b = BookInfo()

str(b) __str__

4) 自定義管理頁面

自定義模型管理類。模型管理類就是告訴django在生成的管理頁面上顯示哪些內容。

1.6模型類屬性命名限制

1)不能是python的保留關鍵字。

2)不容許使用連續的下劃線,這是由django的查詢方式決定的。

3)定義屬性時須要指定字段類型,經過字段類型的參數指定選項,語法以下:

屬性名=models.字段類型(選項)

 

2.Django ORM 經常使用字段和參數

2.1經常使用字段

AutoField

自動增加的IntegerField,一般不用指定,不指定時Django會自動建立屬性名爲id的自動增加屬性

IntegerField

一個整數類型,範圍在 -2147483648 to 2147483647。

CharField

字符類型,必須提供max_length參數, max_length表示字符長度。

BooleanField

布爾字段,值爲True或False

TextField

大文本字段,通常超過4000個字符時使用

DecimalField(max_digits=None, decimal_places=None)

十進制浮點數。參數max_digits表示總位。參數decimal_places表示小數位數

FloatField

浮點數。參數同上

 

DateField:([auto_now=False, auto_now_add=False])

日期。

1)參數auto_now表示每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,默認爲false。

2) 參數auto_now_add表示當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false。

3)參數auto_now_add和auto_now是

相互排斥的,組合將會發生錯誤

 

TimeField

時間,參數同DateField

 

DateTimeField

日期時間,參數同DateField

日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime()實例。

 

FileField

上傳文件字段

 

ImageField

繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片

 

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)
        - 二進制類型

字段合集
字段集合

 

 

2.2自定義字段(瞭解爲主)

class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED'

自定義char類型字段:

複製代碼
class FixedCharField(models.Field):
    """  自定義的char類型的字段類 """ def __init__(self, max_length, *args, **kwargs): super().__init__(max_length=max_length, *args, **kwargs) self.length = max_length def db_type(self, connection): """  限定生成數據庫表的字段類型爲char,長度爲length指定的值 """ return 'char(%s)' % self.length class Class(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=25) # 使用上面自定義的char類型的字段 cname = FixedCharField(max_length=25)
複製代碼

建立的表結構:

 

附ORM字段與數據庫實際字段的對應關係

對應關係:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
對應關係

2.3字段參數

null

用於表示某個字段能夠爲空。

primary_key

若爲True,則該字段會成爲模型的主鍵字段,默認值是False,通常做爲AutoField的選項使用

unique

若是設置爲unique=True 則該字段在此表中必須是惟一的 ,默認值是False

db_index

若是db_index=True 則表明着爲此字段設置數據庫索引,默認值是False

db_column

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

default

爲該字段設置默認值。

blank

 

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

對比:null是數據庫範疇的概念,blank是後臺管理頁面表單驗證範疇的。

經驗:

當修改模型類以後,若是添加的選項不影響表的結構,則不須要從新作遷移,商品的選項中defaultblank不影響表結構。

時間字段獨有

DatetimeField、DateField、TimeField這個三個時間字段,均可以設置以下屬性。

auto_now_add

配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。

auto_now

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

3.關係字段

3.1ForeignKey

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

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

3.1.2字段參數

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

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

on_delete=None,               # 刪除關聯表中的數據時,當前表與其關聯的field的行爲
on_delete=models.CASCADE,     # 刪除關聯數據,與之關聯也刪除
on_delete=models.DO_NOTHING,  # 刪除關聯數據,什麼也不作
on_delete=models.PROTECT,     # 刪除關聯數據,引起錯誤ProtectedError
# models.ForeignKey('關聯表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL,    # 刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空,一對一同理)
# models.ForeignKey('關聯表', on_delete=models.SET_DEFAULT, default='默認值')
on_delete=models.SET_DEFAULT, # 刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值,一對一同理)
on_delete=models.SET,         # 刪除關聯數據,
 a. 與之關聯的值設置爲指定值,設置:models.SET(值)
 b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)

 

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。

 

3.2OneToOneField

一對一字段。

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

示例

一對一的關聯關係多用在當一張表的不一樣字段查詢頻次差距過大的狀況下,將本能夠存儲在一張表的字段拆開放置在兩張表中,而後將兩張表創建一對一的關聯關係。

複製代碼
class Author(models.Model):
    name = models.CharField(max_length=32)
    info = models.OneToOneField(to='AuthorInfo')
    

class AuthorInfo(models.Model):
    phone = models.CharField(max_length=11)
    email = models.EmailField()

 

複製代碼

3.2.1字段參數

to

設置要關聯的表。

to_field

設置要關聯的字段。

on_delete

同ForeignKey字段。

3.3ManyToManyField

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

3.3.1字段參數

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

默認建立第三張表時,數據庫中表的名稱。

3.3.2多對多關聯關係的三種方式 

方式一:自行建立第三張表

複製代碼
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="書名")


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")


# 本身建立第三張表,分別經過外鍵關聯書和做者
class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")
複製代碼

方式二:經過ManyToManyField自動建立第三張表

複製代碼
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="書名")


# 經過ORM自帶的ManyToManyField自動建立第三張表
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")
    books = models.ManyToManyField(to="Book", related_name="authors")
複製代碼

方式三:設置ManyToManyField並指定自行建立的第三張表

複製代碼
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="書名")


# 本身建立第三張表,並經過ManyToManyField指定關聯
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
    # through_fields接受一個2元組('field1','field2'):
    # 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關聯目標模型(book)的外鍵名。


class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")
複製代碼

 

注意:

當咱們須要在第三張關係表中存儲額外的字段時,就要使用第三種方式。

可是當咱們使用第三種方式建立多對多關聯關係時,就沒法使用set、add、remove、clear方法來管理多對多的關係了,須要經過第三張表的model來管理多對多關係。

3.4元信息(class Meta)

ORM對應的類裏面包含另外一個Meta類,而Meta類封裝了一些數據庫的信息。主要字段以下:

db_table

ORM在數據庫中的表名默認是 app_類名,能夠經過db_table能夠重寫表名。

index_together

聯合索引。

unique_together

聯合惟一索引。

ordering

指定默認按什麼字段排序。

只有設置了該屬性,咱們查詢到的結果才能夠被reverse()。

3.5管理器

BookInfo.objects.all()->objects是一個什麼東西呢?

答:objects是Django幫我自動生成的管理器對象,經過這個管理器能夠實現對數據的查詢。

objects是models.Manger類的一個對象。自定義管理器以後Django再也不幫咱們生成默認的objects管理器。

自定義模型管理器類

 

1) 自定義一個管理器類,這個類繼承models.Manger類。

 

2)再在具體的模型類裏定義一個自定義管理器類的對象

 

 

自定義管理器類的應用場景

 

1) 改變查詢的結果集。

 

好比調用BookInfo.books.all()返回的是沒有刪除的圖書的數據。

 

2) 添加額外的方法。

 

管理器類中定義一個方法幫咱們操做模型類對應的數據表

 

使用self.model()就能夠建立一個跟自定義管理器對應的模型類對象

 

 

相關文章
相關標籤/搜索