第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開(kāi)發(fā)者教程

Django 入門(mén)教程

課程導(dǎo)學(xué)
Django 慕課教程使用指南
Django開(kāi)發(fā)實(shí)戰(zhàn)
35 開(kāi)發(fā)實(shí)戰(zhàn)

Django 中內(nèi)嵌的 ORM 模型

本小節(jié)將詳細(xì)為大家介紹 Django 中內(nèi)嵌的 ORM 模型及其使用,這里我會(huì)結(jié)合源碼的方式為大家展示 Django 內(nèi)部 ORM 模型的實(shí)現(xiàn)原理。

1. ORM 介紹

ORM 的概念如下:

對(duì)象關(guān)系映射(Object Relational Mapping,簡(jiǎn)稱(chēng)ORM)模式是一種為了解決面向?qū)ο笈c關(guān)系數(shù)據(jù)庫(kù)存在的互不匹配的現(xiàn)象的技術(shù)。

簡(jiǎn)單的說(shuō),ORM 是通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中。ORM 在業(yè)務(wù)邏輯層和數(shù)據(jù)庫(kù)層之間充當(dāng)了橋梁的作用。ORM 解決的主要問(wèn)題是對(duì)象和關(guān)系的映射。它通常把一個(gè)類(lèi)和一個(gè)表一一對(duì)應(yīng),類(lèi)的每個(gè)實(shí)例對(duì)應(yīng)表中的一條記錄,類(lèi)的每個(gè)屬性對(duì)應(yīng)表中的每個(gè)字段,具體如下圖所示。ORM 提供了對(duì)數(shù)據(jù)庫(kù)的映射,不用直接編寫(xiě) SQL 代碼,只需像操作對(duì)象一樣從數(shù)據(jù)庫(kù)操作數(shù)據(jù)。讓軟件開(kāi)發(fā)人員專(zhuān)注于業(yè)務(wù)邏輯的處理,提高了開(kāi)發(fā)效率。

圖片描述

ORM 模式也是有一定缺點(diǎn)的,它會(huì)在一定程度上犧牲程序的執(zhí)行效率。此外,還存在許多復(fù)雜場(chǎng)景是 ORM 模式無(wú)法解決的,同樣還是需要手動(dòng)編寫(xiě) SQL 語(yǔ)句完成。

2. Django 內(nèi)嵌的 ORM 模型

2.1 Django 中的模型說(shuō)明

在 Django 中,一個(gè)模型(model)會(huì)映射到一個(gè)數(shù)據(jù)庫(kù)表。每個(gè)模型都是一個(gè)Python 類(lèi),它是django.db.models.Model 的子類(lèi),模型的每個(gè)屬性都代表一個(gè)數(shù)據(jù)庫(kù)字段。例如下面的代碼中,我們定義了一個(gè) Member 類(lèi)。每個(gè) model 會(huì)屬于 Django 中的一個(gè)應(yīng)用,我們通常會(huì)將每個(gè)應(yīng)用的 models 寫(xiě)到該應(yīng)用目錄下的 models.py 中。

# first_django_app/hello_app/models.py

from django.db import models

class Member(models.Model):
    sex_choices = (
        (0, '男'),
        (1, '女'),
    )
    name = models.CharField('姓名', max_length=30)
    age = models.CharField('年齡', max_length=30)
    sex = models.SmallIntegerField('性別', choices=sex_choices, default=0)
    occupation = models.CharField('職業(yè)', max_length=30)
    phone_num = models.CharField('手機(jī)號(hào)', max_length=14, null=True)
    email = models.EmailField('郵箱', blank=True)
    city = models.CharField('城市', max_length=30)
    register_date = models.DateTimeField('注冊(cè)時(shí)間', auto_now=True)
    
    def __str__(self):
        return "<%s, %s>" % (self.name, self.phone_num)

    class Meta:
        # 通過(guò)db_table自定義數(shù)據(jù)表名
        db_table = 'member'
    

上面模型類(lèi)的定義中,我們看到幾個(gè)和模型相關(guān)的字段類(lèi),比如 CharField、SmallIntegerField 等。Django 中定義了許多類(lèi)似的字段類(lèi),這些字段類(lèi)和數(shù)據(jù)庫(kù)中字段的類(lèi)型是一一映射的。以 MySQL 為例:

# 源碼地址 django/db/backends/mysql/base.py
# ...

class DatabaseWrapper(BaseDatabaseWrapper):
    vendor = 'mysql'
    display_name = 'MySQL'
    # This dictionary maps Field objects to their associated MySQL column
    # types, as strings. Column-type strings can contain format strings; they'll
    # be interpolated against the values of Field.__dict__ before being output.
    # If a column type is set to None, it won't be included in the output.
    data_types = {
        'AutoField': 'integer AUTO_INCREMENT',
        'BigAutoField': 'bigint AUTO_INCREMENT',
        'BinaryField': 'longblob',
        'BooleanField': 'bool',
        'CharField': 'varchar(%(max_length)s)',
        'DateField': 'date',
        'DateTimeField': 'datetime(6)',
        '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(6)',
        'UUIDField': 'char(32)',
    }
    
    # ...
    
# ...

從上面這部分源碼可以看到,Django 中定義的這些字段類(lèi)都會(huì)和 MySQL 中的字段的類(lèi)型是一一對(duì)應(yīng)的。接下來(lái)介紹常用的 Field 類(lèi)型以及相關(guān)的屬性選項(xiàng)。

2.2 Django 中常用的 Field types

在 Django 模型中,每個(gè)字段都應(yīng)該是相應(yīng) Field 類(lèi)的實(shí)例,以此決定該表在數(shù)據(jù)庫(kù)中保存字段的數(shù)據(jù)類(lèi)型。在上面的源碼中我們看到 Django 內(nèi)部是定義了25個(gè)字段類(lèi),其中常用的 Field 類(lèi)型如下:

  • AutoField:int 自增列,必須填入?yún)?shù) primary_key=True。當(dāng) model 中如果沒(méi)有自增列,則自動(dòng)會(huì)創(chuàng)建一個(gè)列名為 id 的列;

  • BooleanField:布爾類(lèi)型 (True/False),這個(gè)Field不接受null參數(shù),要想使用可以為 null 的布爾類(lèi)型的字段,就要使用 NullBooleanField;

  • CharField:最常用的字段類(lèi),映射到數(shù)據(jù)庫(kù)中會(huì)轉(zhuǎn)換成 varchar 類(lèi)型,使用時(shí)必須傳入 max_length 屬性以定義該字符串的最大長(zhǎng)度,如果超過(guò)254個(gè)字符,就不建議使用 CharField 了,此時(shí)建議使用 TextField;

  • DateField 和 DateTimeField:都是日期時(shí)間的字段類(lèi),注意前者只到天,后者可以精確到毫秒。使用這兩個(gè) Field 可以傳遞以下幾個(gè)參數(shù):

    • auto_now=True:在每次這個(gè)數(shù)據(jù)保存的時(shí)候,都使用當(dāng)前的時(shí)間;
    • auto_now_add=True:在每條數(shù)據(jù)第一次被添加進(jìn)去的時(shí)候,都使用當(dāng)前的時(shí)間;

    此外要注意的是 auto_add_now,auto_now 與 default 是互斥的。

  • DecimalField:處理浮點(diǎn)類(lèi)型的 Field。從上面的源碼可以看到,它有兩個(gè)必須填入的參數(shù):

    • max_digits:數(shù)字允許的最大位數(shù);

    • decimal_places:小數(shù)的最大位數(shù);

  • FloatField:也是處理浮點(diǎn)類(lèi)型的 Field。它和 DecimalField 的區(qū)別就是 Python 中 float 和 decimal 的區(qū)別;

  • IntegerField /BigIntegerField/SmallIntegerField:都是處理整數(shù)類(lèi)型的 Field;

  • TextField:長(zhǎng)文本類(lèi)型 Field,對(duì)應(yīng) MySQL 中的 longtext 類(lèi)型。

2.3 Django 中的 Field options

每種 Field 類(lèi)會(huì)有一些特定的 Field 選項(xiàng),比如 CharField 必須要傳入 max_length 屬性值。但是下面這些屬性對(duì)于所有 Field 類(lèi)都是有效的:

  • null:默認(rèn)為 False。如果為 True 則表明在數(shù)據(jù)庫(kù)中該字段可以為 null;
  • blank:默認(rèn)為 False。如果為 True 則表明在數(shù)據(jù)庫(kù)中該字段可以為不填;
  • choice:設(shè)置可選項(xiàng),表明該字段的值只能從 choice 中選擇,例如上面 Member 表中定義的 sex 字段,只能為 0 或者 1,代表的含義分別為男或者女;
  • default:設(shè)置字段的默認(rèn)值;
  • help_text:設(shè)置說(shuō)明信息;
  • primary_key:如果為 True,表明設(shè)置該字段為主鍵。此時(shí) Django 便不會(huì)再為我們添加默認(rèn)的 id 主鍵了;
  • unique:設(shè)置該字段的值在表中唯一。

2.4 數(shù)據(jù)庫(kù)中生成模型表

接下來(lái),我們需要使用 Django 給我們提供的兩個(gè)命令來(lái)在數(shù)據(jù)庫(kù)中生成 hello_app 應(yīng)用下定義的數(shù)據(jù)模型。注意: Member 類(lèi)映射的表名默認(rèn)是【應(yīng)用名_類(lèi)名小寫(xiě)】,然而在前面的模型代碼中我們通過(guò) model 的 Meta 類(lèi)中的 db_table 參數(shù)改寫(xiě)了數(shù)據(jù)庫(kù)的具體名稱(chēng),所以最后數(shù)據(jù)庫(kù)中生成的表名為 member,而不是 hello_app_member。

(django-manual) [root@server first_django_app]# python manage.py makemigrations hello_app
Migrations for 'hello_app':
  hello_app/migrations/0001_initial.py
    - Create model Member
(django-manual) [root@server first_django_app]# python manage.py migrate hello_app
Operations to perform:
  Apply all migrations: hello_app
Running migrations:
  Applying hello_app.0001_initial... OK

執(zhí)行完成后,此時(shí) hello_app 應(yīng)用下的所有 model 就會(huì)被映射到 MySQL 數(shù)據(jù)庫(kù)中,且會(huì)對(duì)應(yīng)生成相應(yīng)的模型表(此外還有一個(gè)遷移記錄表 django_migrations):

MySQL [django_manual]> show tables;
+-------------------------+
| Tables_in_django_manual |
+-------------------------+
| django_migrations       |
| member                  |
| user                    |
+-------------------------+
3 rows in set (0.00 sec)

我們還可以通過(guò) show create table 表名 命令顯示表的創(chuàng)建語(yǔ)句:

MySQL [django_manual]> show create table member;
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                                                                                                                          |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| member | CREATE TABLE `member` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  `age` varchar(30) NOT NULL,
  `sex` smallint(6) NOT NULL,
  `occupation` varchar(30) NOT NULL,
  `phone_num` varchar(14) NOT NULL,
  `email` varchar(254) NOT NULL,
  `city` varchar(30) NOT NULL,
  `register_date` datetime(6) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

3. 小結(jié)

本小結(jié)中我們介紹了 ORM 的基本概念,然后講解了 Django 中的 model 相關(guān)知識(shí),介紹了模型層中常見(jiàn)的字段類(lèi)型和字段選項(xiàng)。最后實(shí)戰(zhàn)演示了如何通過(guò) Django 提供的命令在數(shù)據(jù)庫(kù)中生成模型層定義的表。接下來(lái)我們會(huì)在生成的表中使用 Django 給我們提供的 ORM 模型對(duì)表進(jìn)行增刪改查操作。