模型層之orm介紹

ORM簡介

查詢數據層次圖解:若是操做mysql,ORM是在pymysq之上又進行了一層封裝前端

  • MVC或者MTV框架中包括一個重要的部分,就是ORM,它實現了數據模型與數據庫的解耦,即數據模型的設計不須要依賴於特定的數據庫,經過簡單的配置就能夠輕鬆更換數據庫,這極大的減輕了開發人員的工做量,不須要面對因數據庫變動而致使的無效勞動
  • ORM是「對象-關係-映射」的簡稱。
#sql中的表                                                      

 #建立表:
     CREATE TABLE employee(                                     
                id INT PRIMARY KEY auto_increment ,                    
                name VARCHAR (20),                                      
                gender BIT default 1,                                  
                birthday DATA ,                                         
                department VARCHAR (20),                                
                salary DECIMAL (8,2) unsigned,                          
              );


  #sql中的表紀錄                                                  

  #添加一條表紀錄:                                                          
      INSERT employee (name,gender,birthday,salary,department)            
             VALUES   ("alex",1,"1985-12-12",8000,"保潔部");               

  #查詢一條表紀錄:                                                           
      SELECT * FROM employee WHERE age=24;                               

  #更新一條表紀錄:                                                           
      UPDATE employee SET birthday="1989-10-24" WHERE id=1;              

  #刪除一條表紀錄:                                                          
      DELETE FROM employee WHERE name="alex"                             





#python的類
class Employee(models.Model):
     id=models.AutoField(primary_key=True)
     name=models.CharField(max_length=32)
     gender=models.BooleanField()
     birthday=models.DateField()
     department=models.CharField(max_length=32)
     salary=models.DecimalField(max_digits=8,decimal_places=2)


 #python的類對象
      #添加一條表紀錄:
          emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保潔部")
          emp.save()
      #查詢一條表紀錄:
          Employee.objects.filter(age=24)
      #更新一條表紀錄:
          Employee.objects.filter(id=1).update(birthday="1989-10-24")
      #刪除一條表紀錄:
          Employee.objects.filter(name="alex").delete()

Django ORM中經常使用字段和參數

一些說明:python

  • 表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的列。mysql

IntegerField

一個整數類型,範圍在 -2147483648 to 2147483647。(通常不用它來存手機號(位數也不夠),直接用字符串存,)git

CharField

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

這裏須要知道的是Django中的CharField對應的MySQL數據庫中的varchar類型,沒有設置對應char類型的字段,可是Django容許咱們自定義新的字段,下面我來自定義對應於數據庫的char類型數據庫

img

DateField

日期字段,日期格式 YYYY-MM-DD,至關於Python中的datetime.date()實例。django

DateTimeField

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

字段參數

null

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

unique

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

db_index

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

default

爲該字段設置默認值。

DateField和DateTimeField

auto_now_add

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

auto_now

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

關係字段

ForeignKey

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

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

字段參數

to

設置要關聯的表

to_field

設置要關聯的表的字段

on_delete

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

models.CASCADE

刪除關聯數據,與之關聯也刪除

db_constraint

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

其他字段參數

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


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


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


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


models.SET

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

OneToOneField

一對一字段。

一般一對一字段用來擴展已有字段。(通俗的說就是一我的的全部信息不是放在一張表裏面的,簡單的信息一張表,隱私的信息另外一張表,之間經過一對一外鍵關聯)

字段參數

to

設置要關聯的表。

to_field

設置要關聯的字段。

on_delete

當刪除關聯表中的數據時,當前表與其關聯的行的行爲。(參考上面的例子)

ManyToManyField

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

to

設置要關聯的表

同ForeignKey字段。

同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

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

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

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

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來管理多對多關係。

元信息

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

db_table

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

index_together

聯合索引。

unique_together

聯合惟一索引。

ordering

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

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

class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)

        class Meta:
            # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名
            db_table = "table_name"

            # 聯合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 聯合惟一索引
            unique_together = (("driver", "restaurant"),)
            
            ordering = ('name',)
            
            # admin中顯示的表名稱
            verbose_name='哈哈'

            # verbose_name加s
            verbose_name_plural=verbose_name

自定義字段(瞭解)

自定義字段在實際項目應用中可能會常常用到,這裏須要對他留個印象!

自定義char類型字段:

from django.db import models

# Create your models here.
#Django中沒有對應的char類型字段,可是咱們能夠本身建立
class FixCharField(models.Field):
    '''
    自定義的char類型的字段類
    '''
    def __init__(self,max_length,*args,**kwargs):
        self.max_length=max_length
        super().__init__(max_length=max_length,*args,**kwargs)

    def db_type(self, connection):
        '''
        限定生成的數據庫表字段類型char,長度爲max_length指定的值
        :param connection:
        :return:
        '''
        return 'char(%s)'%self.max_length
#應用上面自定義的char類型
class Class(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=32)
    class_name=FixCharField(max_length=16)
    gender_choice=((1,'男'),(2,'女'),(3,'保密'))
    gender=models.SmallIntegerField(choices=gender_choice,default=3)

字段合集(爭取記憶)

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

字段屬性

(1)null
 
若是爲True,Django 將用NULL 來在數據庫中存儲空值。 默認值是 False.
 
(1)blank
 
若是爲True,該字段容許不填。默認爲False。
要注意,這與 null 不一樣。null純粹是數據庫範疇的,而 blank 是數據驗證範疇的。
若是一個字段的blank=True,表單的驗證將容許該字段是空值。若是字段的blank=False,該字段就是必填的。
 
(2)default
 
字段的默認值。能夠是一個值或者可調用對象。若是可調用 ,每有新對象被建立它都會被調用。
 
(3)primary_key
 
若是爲True,那麼這個字段就是模型的主鍵。若是你沒有指定任何一個字段的primary_key=True,
Django 就會自動添加一個IntegerField字段作爲主鍵,因此除非你想覆蓋默認的主鍵行爲,
不然不必設置任何一個字段的primary_key=True。
 
(4)unique
 
若是該值設置爲 True, 這個數據字段的值在整張表中必須是惟一的
 
(5)choices
由二元組組成的一個可迭代對象(例如,列表或元組),用來給字段提供選擇項。 若是設置了choices ,默認的表單將是一個選擇框而不是標準的文本框,<br>並且這個選擇框的選項就是choices 中的選項。

orm字段與MySQL字段對應關係

對應關係:
    '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)',

choice參數

choice參數
    能夠用作
        用戶性別
        用戶學歷
        用戶工做狀態
        客戶來源
        ...
class Userinfo(models.Model):
    name = models.CharField(max_length=32)
    password = models.IntegerField(default=123)
    choice = (
        (1,'male'),
        (2,'female'),
        (3,'other')
    )
    gender = models.IntegerField(choices=choice)
        """
        1.若是我存的是上面元組中數字會怎麼樣
        2.若是我存的數字不在元組範圍內又會怎樣
            1.數字沒有對應關係 是能夠存的
        """

前端獲取

{{ user_obj.get_gender_display }}

後端獲取

from app01 import models
ser_obj = models.Userinfo.objects.filter(pk=4).first()
        print(user_obj.username)
        print(user_obj.gender)
        # 針對choices字段 若是你想要獲取數字所對應的中文 你不能直接點字段
        # 固定句式   數據對象.get_字段名_display()  當沒有對應關係的時候 該句式獲取到的仍是數字
        print(user_obj.get_gender_display())

能夠這樣使用

record_choices = (('checked', "已簽到"),
                      ('vacate', "請假"),
                      ('late', "遲到"),
                      ('noshow', "缺勤"),
                      ('leave_early', "早退"),
                      )
        record = models.CharField("上課紀錄", choices=record_choices, default="checked", 
    
    
        
        
        score_choices = ((100, 'A+'),
                     (90, 'A'),
                     (85, 'B+'),
                     (80, 'B'),
                     (70, 'B-'),
                     (60, 'C+'),
                     (50, 'C'),
                     (40, 'C-'),
                     (0, ' D'),
                     (-1, 'N/A'),
                     (-100, 'COPY'),
                     (-1000, 'FAIL'),
                     )
        score = models.IntegerField("本節成績", choices=score_choices, default=-1)

數據模型定義(批量操做數據)

from django.db import models
# Create your models here.
class Test(models.Model):
    name = models.CharField(max_length=32, null=True, default=None)
    age = models.IntegerField(max_length=32, null=True, default=None)

img

在urls.py文件添加一個路徑

urlpatterns = [
    path('admin/', admin.site.urls),
    path("favicon.ico", RedirectView.as_view(url='static/favicon.ico')),
    re_path('^index/',views.index),
]

在views.py添加數據

批量添加單個字段

def index(request):
    product_list_to_insert = list()
    for i in range(1000):
        product_list_to_insert.append(models.Test(name='123'))
    models.Test.objects.bulk_create(product_list_to_insert)

批量添加多個字段

# ############### 添加數據 ###############    
def index(request):
    import random

    product_list_to_insert = list()
    for x in range(100):
       #注意下面的添加方式 product_list_to_insert.append(models.Test(name='apollo' + str(x), age=random.randint(18, 89)))
    models.Test.objects.bulk_create(product_list_to_insert)
    return render(request, 'index.html')

批量更新數據

批量更新數據時,先進行數據過濾,而後再調用update方法進行一次性地更新。下面的語句將生成相似update....frrom....的SQL語句。
# ############### 更新數據 ###############
Test.objects.filter(name__contains='apollo1').update(name='Jack')

批量刪除數據

批量更新數據時,先是進行數據過濾,而後再調用delete方法進行一次性刪除。
下面的語句講生成相似delete from ... where ... 的SQL語句。
# ############### 刪除數據 ###############
Test.objects.filter(name__contains='jack').delete()

建立多對多表關係的三種方式

方式1:全自動建立(推薦使用**)

優勢:好處在於 django orm會自動幫你建立第三張關係表
缺點:可是它只會幫你建立兩個表的關係字段(倆個book_id,author_id) 不會再額外添加字段
雖然方便 可是第三張表的擴展性較差 沒法隨意的添加額外的字段

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author')

class Author(models.Models):
    ...

方式2:純手動(不推薦使用)

本身手動添加外鍵

優勢:好處在於第三張表是能夠任意的添加額外的字段

缺點:不足之處是在於orm查詢的時候,不少方法不支持,查詢的時候很是的麻煩

class Book(models.Model):
                ...
                
class Author(models.Models):
    ...
            
class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)

方式3半自動(推薦使用,擴展性高)

3.半自動(推薦使用******)
手動建表 可是你會告訴orm 第三張表是你本身建的
orm只須要給我提供方便的查詢方法
第三種雖然可使用orm查詢方法,可是不支持使用下面的方法:
add()
set()
remove()
clear()

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))#告訴django,是和那個表多對多關聯,關聯表是什麼,關聯的字段是什麼
class Author(models.Model):
    ...
    #books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)#創建額外的字段

注意

  1. 半自動 必定要加兩個額外的參數: through='Book2Author', through_fields=('book','author')
  2. 後面字段的順序:由第三張表經過哪一個字段查詢單表 就把哪一個字段放前面
  3. 在設計項目的時候 必定要給本身留後路 防止後續的迭代更新 ,所以推薦使用方法3
相關文章
相關標籤/搜索