天天看點

Django web 架構學習之旅(3)《Django Web 架構》

《Django Web 架構》

目錄

  • 靜态檔案
  • Django中的應用 - app
    • 什麼是應用(app)
    • 建立應用app
    • Django應用的結構組成
  • 資料庫 和 模型
    • Django下使用mysql資料庫
    • 資料庫遷移的錯誤處理方法
  • 模型(Models)
  • Python 資料庫模型 - Models
    • 字段選項
    • 資料庫的操作(CRUD操作)
      • 建立資料對象
      • 查詢資料
      • 修改資料
      • 删除資料
    • 聚合查詢
      • 不帶分組聚合
      • 分組聚合
    • F對象
    • Q對象

靜态檔案

  1. 什麼是靜态檔案
    • 不能與伺服器端做動态互動的檔案都是靜态檔案
    • 如:圖檔,css,js,音頻,視訊,html檔案(部分)
  2. 靜态檔案配置
    • 在 settings.py 中配置一下兩項内容:
    1. 配置靜态檔案的通路路徑
      • 通過哪個url位址找靜态檔案
      • STATIC_URL = ‘/static/’
      • 說明:
        • 指定通路靜态檔案時是需要通過 /static/xxx或 127.0.0.1:8000/static/xxx
        • xxx 表示具體的靜态資源位置
    2. 配置靜态檔案的存儲路徑
      • 靜态檔案在伺服器端的儲存位置
      • STATICFILES_DIRS=(os.path.join(BASE_DIR,‘static’),)
    3. 示例:
      # file: setting.py
      STATICFILES_DIRS = [
          os.path.join(BASE_DIR, "static")
      ]
                 
  3. 通路靜态檔案
    1. 使用靜态檔案的通路路徑進行通路
      • 通路路徑: STATIC_URL=/static/
      • 示例:
        <img src="/static/images/lena.jpg">
        <img src="http://127.0.0.1:8000/static/images/lena.jpg">
                   
    2. 通過 {% static %}标簽通路靜态檔案

      {% static %}表示的就是靜态檔案通路路徑

      1. 加載 static

        {% load static %}

      2. 使用靜态資源時

        文法:{% static ‘靜态資源路徑’ %}

        <img src="{% static ‘images/lena.jpg’ %}">

    • 示例:
      # file: url.py
      from . import views
      
      urlpatterns = [
          url(r'^admin/', admin.site.urls),
          url(r'^show_image', views.show_image)
      ]
      # file: views.py
      from django.shortcuts import render
      
      def show_image(request):
          return render(request, "show_image.html")
                 
      <html>
      <head></head>
      <body>
      <h1>this is lena!</h1>
      <img src="/static/images/lena.jpg">
      <h1>this is templates lena!</h1>
      {% load static %}
      <img src="{% static 'images/lena.jpg' %}">
      </body>
      </html>
                 

Django中的應用 - app

什麼是應用(app)

  • 應用在Django項目中是一個獨立的業務子產品,可以包含自己的路由,視圖,… …
  • Django中,主檔案夾是不處理使用者具體請求的.主檔案夾的作用是做項目的初始化以及請求的分發(分布式請求處理).具體的請求是由應用來進行處理的

建立應用app

  • 建立應用的指令
    • python3 manage.py startapp 應用名稱
    • 如:
      • python3 manage.py startapp music

Django應用的結構組成

1. `migrations` 檔案夾
    - 儲存資料遷移的中間檔案
2. `__init__.py`
    - 應用子包的初始化檔案
3. `admin.py`
    - 應用的背景管理配置檔案
4. `apps.py`
    - 應用的屬性配置檔案
5. `models.py`
    - 與資料庫相關的模型映射類檔案
6. `tests.py`
    - 應用的單元測試檔案
7. `views.py`
    - 定義視圖處理函數的檔案
           
  • 配置安裝應用
    • 在 settings.py 中配置應用, 讓此應用能和整個項目融為一體
      # file : settings.py 
      INSTALLED_APPS = [
          ... ...,
          '自定義應用名稱'
      ]
      
                 
    • 如:
      INSTALLED_APPS = [
          # ....
          'user',  # 使用者資訊子產品
          'music',  # 收藏子產品
      ]
                 
  • 應用的分布式路由
    • 使用include 函數讓某個正則比對後關聯分支到某個app
    # file : <項目名>/urls.py
    from django.conf.urls import include
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^music/', include('music.urls')),
        url(r'^sport/',include('sport.urls')),
        url(r'^news/',include('news.urls')),
    ]
    # file : <App名>/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        # 購物車子產品用到的路由
        url(r'^page1', views.page1),
        url(r'^page2', views.page2),
        url(r'^page3', views.page3),
        # ...
    ]
    
    
    
               

資料庫 和 模型

Django下使用mysql資料庫

  1. 安裝 pymysql包
    • 用作 python 和 mysql 的接口
      • $ sudo pip3 install pymysql

    • 安裝 mysql 用戶端(非必須)

      $ sudo pip3 install mysqlclient

  2. 建立 和 配置資料庫
    1. 建立資料庫
      • 建立

        create database 資料庫名 default charset utf8 collate utf8_general_ci;

    2. 資料庫的配置
      • sqlite 資料庫配置
      # file: settings.py
      DATABASES = {
          'default': {
                  'ENGINE': 'django.db.backends.sqlite3',
                  'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
          }
      }
                 
      • mysql 資料庫配置
      DATABASES = {
          'default' : {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'mywebdb',  # 資料庫名稱,需要自己定義
              'USER': 'root',
              'PASSWORD': '123456',  # 管理者密碼
              'HOST': '127.0.0.1',
              'PORT': 3306,
          }
      }
                 
    3. 關于資料為的SETTING設定
      1. ENGINE
        • 指定資料庫的後端引擎
        'django.db.backends.mysql'
        'django.db.backends.sqlite3'
        'django.db.backends.oracle'
        'django.db.backends.postgresql'
                   
        • mysql引擎如下:
          • ‘django.db.backends.mysql’
      2. NAME
        • 指定要連接配接的資料庫的名稱
        • 'NAME': 'mywebdb'

      3. USER
        • 指定登入到資料庫的使用者名
        • 'USER':'root'

      4. PASSWORD
        • 接資料庫時使用的密碼。
        • 'PASSWORD':'123456'

      5. HOST
        • 連接配接資料庫時使用哪個主機。
        • 'HOST':'127.0.0.1'

      6. PORT
        • 連接配接資料庫時使用的端口。
        • 'PORT':'3306'

    4. 添加 mysql 支援
      • 安裝pymysql 子產品
        • $ sudo pip install pymysql

      • 修改項目中__init__.py 加入如下内容來提供pymysql引擎的支援
        import pymysql
        pymysql.install_as_MySQLdb()
                   
  3. 資料庫的遷移
    • 遷移是Django同步您對模型所做更改(添加字段,删除模型等) 到您的資料庫模式的方式
    1. 生成或更新遷移檔案
      • 将每個應用下的models.py檔案生成一個中間檔案,并儲存在migrations檔案夾中
      • python3 manage.py makemigrations

    2. 執行遷移腳本程式
      • 執行遷移程式實作遷移。将每個應用下的migrations目錄中的中間檔案同步回資料庫
      • python3 manage.py migrate

    3. 檢視遷移執行的SQL語句
      • 将 sqlmigrate, 顯示遷移的sql語句
      • python3 manage.py sqlmigrate

資料庫遷移的錯誤處理方法

  • 當執行

    $ python3 manage.py makemigrations

    出現如下遷移錯誤時的處理方法
    • 錯誤資訊
      $ python3 manage.py makemigrations
      You are trying to change the nullable field 'title' on book to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
      Please select a fix:
      1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
      2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
      3) Quit, and let me add a default in models.py
      Select an option: 
                 
    • 翻譯為中文如下:
      $ python3 manage.py makemigrations
      您試圖将圖書上的可空字段“title”更改為非空字段(沒有預設值);我們不能這樣做(資料庫需要填充現有行)。
      請選擇修複:
      1)現在提供一次性預設值(将對所有現有行設定此列的空值)
      2)暫時忽略,讓我自己處理空值的現有行(例如,因為您在以前的資料遷移中添加了RunPython或RunSQL操作來處理空值)
      3)退出,讓我在models.py中添加一個預設值
      選擇一個選項:
                 
    • 錯誤原因
      • 當将如下代碼
      class Book(models.Model):
          title = models.CharField("書名", max_length=50, null=True)
                 
      • 去掉 null=True 改為如下内容時會出現上述錯誤
      class Book(models.Model):
          title = models.CharField("書名", max_length=50)
                 
      • 原理是 此資料庫的title 字段由原來的可以為NULL改為非NULL狀态,意味着原來這個字段可以不填值,現在改為必須填定一個值,那填什麼值呢?此時必須添加一個預設值。
    • 處理方法:
      1. 選擇1 手動給出一個預設值,在生成 bookstore/migrations/000x_auto_xxxxxxxx_xxxx.py 檔案時自動将輸入的值添加到default參數中
      2. 暫時忽略,以後用其它的指令處理預設值問題(不推薦)
      3. 退出目前生成遷移檔案的過程,自己去修改models.py, 新增加一個

        default=XXX

        的預設值(推薦使用)
  • 資料庫的遷移檔案混亂的解決辦法
    1. 删除 所有 migrations 裡所有的 000?_XXXX.py (

      __init__.py

      除外)
    2. 删除 資料表
      • sql> drop database mywebdb;
    3. 重新建立 資料表
      • sql> create datebase mywebdb default charset…;
    4. 重新生成migrations裡所有的 000?_XXXX.py
      • python3 manage.py makemigrations
    5. 重新更新資料庫
      • python3 manage.py migrate

模型(Models)

  • 模型是提供資料資訊的資料庫接口。
  • 模型是資料的唯一的、确定的資訊源。 它包含你所儲存資料的必要字段和行為。
  • 通常,每個模型對應資料庫中唯一的一張表。每個模型的執行個體對應資料表中的一條記錄
  • 模型說明:
    • 每個模型都是一個Python類,每個模型都是django.db.models.Model的子類。
    • 每一個模型屬性都代表資料庫中的一個表。
    • 通過所有這一切,Django為你提供一個自動生成的資料庫通路API;

Python 資料庫模型 - Models

  1. ORM架構
    • ORM(Object Relationship Mapping)即對象關系映射,它允許你使用類和對象對資料庫進行互動(使用類和對象和使用 SQL一樣且更友善各種操作)。
    • ORM
      Object Relationship Mapping
        對象    關系         映射
                 
    • 三大特征:
      1. 表 到 類的映射
      2. 資料類型的映射
      3. 關系映射
  2. 模型示例:
    • 此示例為添加一個bookstore_book 資料表來存放圖書館中書目資訊
    • 添加一個 bookstore 的 app
    $ python3 manage.py startapp bookstore
               
    • 添加模型類并注冊app
    # file : bookstore/models.py
    from django.db import models
    
    class Book(models.Model):
        title = models.CharField("書名", max_length=50)
        price = models.DecimalField('定價', max_digits=7, decimal_places=2)
    # file : setting.py
    INSTALLED_APPS = [
        ...
        'bookstore',
    ]
               
    • 生成遷移腳本檔案

      bookstore/migrations/0001_initial.py

      并進行遷移
    $ python3 manage.py makemigrations
    Migrations for 'bookstore':
    bookstore/migrations/0001_initial.py
        - Create model Book
    $ python3 manage.py migrate
    Operations to perform:
    Apply all migrations: admin, auth, bookstore, contenttypes, sessions
    Running migrations:
    Applying bookstore.0001_initial... OK
               
    • 檢視資料表
    $ mysql -u root -p
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mygoods            |
    | mysql              |
    | mywebdb            |
    | onlybuyp           |
    | performance_schema |
    | sys                |
    | test_db            |
    +--------------------+
    8 rows in set (0.00 sec)
    
    mysql> use mywebdb
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> show tables;
    +----------------------------+
    | Tables_in_mywebdb          |
    +----------------------------+
    | auth_group                 |
    | auth_group_permissions     |
    | auth_permission            |
    | auth_user                  |
    | auth_user_groups           |
    | auth_user_user_permissions |
    | bookstore_book             |  <<== 新加表
    | django_admin_log           |
    | django_content_type        |
    | django_migrations          |
    | django_session             |
    +----------------------------+
    11 rows in set (0.00 sec)
    
    mysql> desc bookstore_book;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | title | varchar(50)  | NO   |     | NULL    |                |
    | price | decimal(7,2) | NO   |     | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
               
    • 表bookstore_book 即為模型 Book 類對應的資料表
      • id 為主鍵,當設定主鍵時會自動添加id字段為主鍵
      • 如果更新模型類 models.py 中的内容時需要運作 makemigrations 和 migrate 子命名來更新和同步資料庫
      • 在開發階段如果同步資料庫出錯。用

        sql> drop database 資料庫名

        删除資料庫後重新遷移資料庫
      • 在 xxx_app/migrations/*.py 下的檔案是自動生成的遷移腳本檔案,可以手動删除且在下一次遷移時自動生成
  1. 編寫模型類Models
    • 模型類需繼承

      自django.db.models.Model

      1. Models的文法規範
        from django.db import models
        class CLASSNAME類名(models.Model):
            NAME=models.FIELD_TYPE(FIELD_OPTIONS)
                   
      2. CLASSNAME
        • 實體類名,表名組成一部分,建議類名首字母大寫
        • 預設表名組成規範:
          • 應用名稱_classname
      3. NAME
        • 屬性名,映射回資料庫就是字段名
      4. FIELD_TYPE
        • 字段類型:映射到表中的字段的類型
  2. FIELD_TYPE 類型及含義
    1. BooleanField()
      • 資料庫類型:tinyint(1)
      • 程式設計語言中:使用True或False來表示值
      • 在資料庫中:使用1或0來表示具體的值
    2. CharField()
      • 資料庫類型:varchar
      • 注意:
        • 必須要指定max_length參數值
    3. DateField()
      • 資料庫類型:date
      • 作用:表示日期
      • 程式設計語言中:使用字元串來表示具體值
      • 參數:
        • DateField.auto_now: 每次儲存對象時,自動設定該字段為目前時間(取值:True/False)。
        • DateField.auto_now_add: 當對象第一次被建立時自動設定目前時間(取值:True/False)。
        • DateField.default: 設定目前時間(取值:字元串格式時間如: ‘2019-6-1’)。
        • 以上三個參數隻能多選一
    4. DateTimeField()
      • 資料庫類型:datetime(6)
      • 作用:表示日期和時間
      • auto_now_add=True
    5. DecimalField()
      • 資料庫類型:decimal(x,y)
      • 程式設計語言中:使用小數表示該列的值
      • 在資料庫中:使用小數
      • 參數:
        • DecimalField.max_digits: 位數總數,包括小數點後的位數。 該值必須大于等于decimal_places.
        • DecimalField.decimal_places: 小數點後的數字數量
      • 示例:
        money=models.DecimalField(
            max_digits=7,
            decimal_places=2
        )
                   
    6. FloatField()
      • 資料庫類型:double
      • 程式設計語言中和資料庫中都使用小數表示值
    7. EmailField()
      • 資料庫類型:varchar
      • 程式設計語言和資料庫中使用字元串
    8. IntegerField()
      • 資料庫類型:int
      • 程式設計語言和資料庫中使用整數
    9. URLField()
      • 資料庫類型:varchar(200)
      • 程式設計語言和資料庫中使用字元串
    10. ImageField()
      • 資料庫類型:varchar(100)
      • 作用:在資料庫中為了儲存圖檔的路徑
      • 程式設計語言和資料庫中使用字元串
      • 示例:
        image=models.ImageField(
            upload_to="static/images"
        )
                   
      • upload_to:指定圖檔的上傳路徑

        在背景上傳時會自動的将檔案儲存在指定的目錄下

    11. TextField()
      • 資料庫類型:longtext
      • 作用:表示不定長的字元資料
    • 參考文檔https://yiyibooks.cn/xx/Django_1.11.6/ref/models/fields.html

字段選項

  1. FIELD_OPTIONS
    • 字段選項,指定建立的列的額外的資訊
    • 允許出現多個字段選項,多個選項之間使用,隔開
    1. primary_key
      • 如果設定為True,表示該列為主鍵
    2. null
      • 如果設定為True,表示該列值允許為空
      • 預設為False
    3. default
      • 設定所在列的預設值
    4. db_index
      • 如果設定為True,表示為該列增加索引
    5. unique
      • 如果設定為True,表示該列的值唯一
    6. db_column
      • 指定列的名稱,如果不指定的話則采用屬性名作為列名
ex:
        建立一個屬性,表示使用者名稱,長度30個字元,必須是唯一的,不能為空,添加索引

        name=models.CharField(max_length=30,unique=True,null=False,db_index=True)
           
  • 文檔參見:
    • https://yiyibooks.cn/xx/Django_1.11.6/ref/models/fields.html?highlight=booleanfield
    • https://docs.djangoproject.com/zh-hans/2.2/ref/models/fields/#field-attribute-reference
  • 示例:
# file : bookstore/models.py
from django.db import models

class Book(models.Model):
    title = models.CharField("書名", max_length=50)
    price = models.DecimalField('定價', max_digits=7, decimal_places=2)
    pub_house = models.CharField("出版社", max_length=50, default='清華大學出版社')
    pub_date = models.DateField('出版時間', default='1970-1-1')
    market_price = models.DecimalField('市價', max_digits=7, decimal_places=2, default=9999)
           
# file : bookstore/views.py
from django.http import HttpResponse
from . import models

def init_books(request):
    models.Book.objects.create(title='C', price=30, market_price=35, pub_house="清華大學出版社")
    models.Book.objects.create(title='C++', price=40, market_price=45, pub_house="清華大學出版社")
    models.Book.objects.create(title='Java', price=50, market_price=55, pub_house="清華大學出版社")
    models.Book.objects.create(title='Python', price=20, market_price=25, pub_house="清華大學出版社")
    models.Book.objects.create(title='Python3', price=60, market_price=65, pub_house="清華大學出版社")
    models.Book.objects.create(title='Django', price=70, market_price=75, pub_house="清華大學出版社")
    models.Book.objects.create(title='JQuery', price=90, market_price=85, pub_house="機械工業出版社")
    models.Book.objects.create(title='Linux', price=80, market_price=65, pub_house="機械工業出版社")
    models.Book.objects.create(title='Windows', price=50, market_price=35, pub_house="機械工業出版社")

    abook = models.Book(title="HTML5", price=90, market_price=105, pub_date='2019-1-1')  # 建立新書
    abook.save()  # 儲存

    return HttpResponse("初始化成功")

           
  • 第一次執行視圖views.py 中的init_books()函數時結果
mysql> select * from bookstore_book;
+----+---------+-------+--------------+------------+----------------+
| id | title   | price | market_price | pub_date   | pub_house      |
+----+---------+-------+--------------+------------+----------------+
|  1 | C       | 30.00 |        35.00 | 1970-01-01 | 清華大學出版社 |
|  2 | C++     | 40.00 |        45.00 | 1970-01-01 | 清華大學出版社 |
|  3 | Java    | 50.00 |        55.00 | 1970-01-01 | 清華大學出版社 |
|  4 | Python  | 20.00 |        25.00 | 1970-01-01 | 清華大學出版社 |
|  5 | Python3 | 60.00 |        65.00 | 1970-01-01 | 清華大學出版社 |
|  6 | Django  | 70.00 |        75.00 | 1970-01-01 | 清華大學出版社 |
|  7 | JQuery  | 90.00 |        85.00 | 1970-01-01 | 機械工業出版社 |
|  8 | Linux   | 80.00 |        65.00 | 1970-01-01 | 機械工業出版社 |
|  9 | Windows | 50.00 |        35.00 | 1970-01-01 | 機械工業出版社 |
| 10 | HTML5   | 90.00 |       105.00 | 2019-01-01 | 清華大學出版社 |
+----+---------+-------+--------------+------------+----------------+
10 rows in set (0.00 sec)
           

資料庫的操作(CRUD操作)

  • CRUD是指在做計算處理時的增加(Create)、讀取查詢(Read)、更新(Update)和删除(Delete)
  • 資料換的增冊改查可以通過模型的管理器實作
    • MyModel.objects 是管理器對象
建立資料對象
  • Django 使用一種直覺的方式把資料庫表中的資料表示成Python 對象
  • 建立資料中每一條記錄就是建立一個資料對象
    1. Entry.objects.create(屬性=值, 屬性=值)
      • 傳回值: 傳回建立好的實體對象
    2. 建立Entry對象,并調用 save() 進行儲存
      obj = Entry(屬性=值,屬性=值)
      obj.屬性=值
      obj.save()
      無傳回值,儲存成功後,obj會被重新指派
                 
    3. 使用字典建立對象,并調用save()進行儲存
      dic = {
          '屬性1':'值',
          '屬性2':'值2',
      }
      
      obj = Entry(**dic)
      obj.save()
                 
    4. 示例1:
      try:
          abook = Book.objects.create(title='Python', pub='清華大學出版社')
          print(abook)
      except:
          print('建立對象失敗')
                 
    5. 示例2:
      try:
          abook = Book(title='Python', pub='清華大學出版社')
          abook.save
          print(abook)
      except:
          print('建立對象失敗')
                 
    6. 示例3:
      try:
          abook = Book()
          abook.title='Python'
          abook.pub='清華大學出版社'
          abook.save
          print(abook)
      except:
          print('建立對象失敗')
                 
查詢資料
  • 資料庫的查詢需要使用管理器對象進行
  • 通過 Entry.objects 管理器方法調用查詢接口
    方法 說明
    all() 查詢全部記錄,傳回QuerySet查詢對象
    get() 查詢符合條件的單一記錄
    filter() 查詢符合條件的多條記錄
    exclude() 查詢符合條件之外的全部記錄
  1. all()方法
    • 方法: all()
    • 用法: Entry.objects.all()
    • 作用: 查詢Entry實體中所有的資料
      • 等同于
        • select * from tabel
    • 傳回值: QuerySet容器對象,内部存放Entry 執行個體
    • 示例:
      from bookstore import models
      books = models.Book.object.all()
      for book in books:
          print("書名", book.title, '出版社:', book.pub)
                 
  2. 在模型類中定義

    def __str__(self):

    方法可以将自定義預設的字元串
    class Book(models.Model):
        title = ...
        def __str__(self):
            return "書名: %s, 出版社: %s, 定價: %s" % (self.title, self.pub, self.price)
               
  3. 查詢傳回指定列(字典表示)
    • 方法: values(‘列1’, ‘列2’)
    • 用法: Entry.objects.values(…)
    • 作用: 查詢部分列的資料并傳回
      • select 列1,列2 from xxx
    • 傳回值: QuerySet
      • 傳回查詢結果容器,容器記憶體字典,每個字典代表一條資料,
      • 格式為: {‘列1’: 值1, ‘列2’: 值2}
    • 示例:
      from bookstore import models
      books = models.Book.objects.values("title", "pub")
      for book in books:
          print("書名", book["title"], '出版社:', book['pub'])
          print("book=", book)
                 
  4. 查詢傳回指定列(元組表示)
    • 方法:values_list(‘列1’,‘列2’)
    • 用法:Entry.objects.values_list(…)
    • 作用:
      • 傳回元組形式的查詢結果
    • 傳回值: QuerySet容器對象,内部存放

      元組

      • 會将查詢出來的資料封裝到元組中,再封裝到查詢集合QuerySet中
    • 示例:
      from bookstore import models
      books = models.Book.objects.values_list("title", "pub")
      for book in books:
          print("book=", book)  # ('Python', '清華大學出版社')...
                 
  5. 排序查詢
    • 方法:order_by
    • 用法:Entry.objects.order_by(’-列’,‘列’)
    • 作用:
      • 與all()方法不同,它會用SQL 語句的ORDER BY 子句對查詢結果進行根據某個字段選擇性的進行排序
    • 說明:
      • 預設是按照升序排序,降序排序則需要在列前增加’-'表示
    • 示例:
      from bookstore import models
      books = models.Book.objects.order_by("price")
      for book in books:
          print("書名:", book.title, '價格:', book.price)
                 
  6. 根據條件查詢多條記錄
    • 方法: filter(條件)
    • 文法:
      Entry.objects.filter(屬性1=值1, 屬性2=值2)
                 
    • 傳回值:
      • QuerySet容器對象,内部存放 Entry 執行個體
    • 說明:
      • 當多個屬性在一起時為與關系,即當

        Books.objects.filter(price=20, pub="清華大學出版社")

        傳回價格為20

        出版社為"清華大學出版社"的全部圖書
    • 示例:
      # 查詢書中出版社為"清華大學出版社"的圖書
      from bookstore import models
      books = models.Book.objects.filter(pub="清華大學出版社")
      for book in books:
          print("書名:", book.title)
      
      2. 查詢Author實體中id為1并且isActive為True的
          - authors=Author.objects.filter(id=1,isActive=True)
                 

字段查找

  • 字段查詢是指如何指定SQL語句中 WHERE 子句的内容。
  • 字段查詢需要通過QuerySet的filter(), exclude() and get()的關鍵字參數指定。
  • 非等值條件的建構,需要使用字段查詢
  • 示例:
    # 查詢作者中年齡大于30
    Author.objects.filter(age__gt = 30)
    # 對應
    SELECT .... WHERE AGE > 35;
               
查詢謂詞
  • 每一個查詢謂詞是一個獨立的查詢功能
  1. __exact

    : 等值比對
    Author.objects.filter(id__exact=1)
    select * from author where id = 1
               
  2. __contains

    : 包含指定值
    Author.objects.filter(name__contains='w')
    select * from author where name like '%w%'
               
  3. __startswith

    : 以 XXX 開始
  4. __endswith

    : 以 XXX 開始
  5. __gt

    : 大于指定值
    Author.objects.filer(age__gt=50)
    select * from author where age > 50
               
  6. __gte

    : 大于等于
  7. __lt

    : 小于
  8. __lte

    : 小于等于
  9. __in

    : 查找資料是否在指定範圍内
    • 示例
    Author.objects.filter(country__in=['中國','日本','南韓'])
    # 等同于
    select * from author where country in ('中國','日本','南韓')
               
  10. __range

    : 查找資料是否在指定的區間範圍内
    # 查找年齡在某一區間内的所有作者
    Author.objects.filter(age__range=(35,50))
    # 等同于
    SELECT ... WHERE Author BETWEEN 35 and 50;
               
  11. 詳細内容參見: https://yiyibooks.cn/xx/Django_1.11.6/ref/models/querysets.html
  • 示例
    Entry.objects.filter(id__gt=4)
    SQL等效:
    
    SELECT ... WHERE id > 4;
               
  • 練習:
    1. 查詢Author表中age大于等于85的資訊
      • Author.objects.filter(age__gte=85)

    2. 查詢Author表中姓王的人的資訊
      • Author.objects.filter(name__startswith='王')

    3. 查詢Author表中Email中包含"wc"的人的資訊
      • Author.objects.filter(email__contains='in')

  1. 不等的條件篩選
    • 文法:

      Entry.objects.exclude(條件)

    • 作用:
      • 傳回不包含此

        條件

        的 作部的資料集
    • 示例:
      • 查詢

        清華大學出版社,價格大于50

        以外的全部圖書
      books = models.Book.objects.exclude(pub=清華大學出版社, price__lt=50)
      for book in books:
          print(book)
                 
  2. 查詢指定的一條資料
    • 文法:

      Entry.objects.get(條件)

    • 作用:
      • 傳回滿足條件的唯一一條資料
    • 傳回值:
      • Entry 對象
    • 說明:
      • 該方法隻能傳回一條資料
      • 查詢結果多餘一條資料則抛出,Model.MultipleObjectsReturned異常
      • 查詢結果如果沒有資料則抛出Model.DoesNotExist異常
    • 示例:
      from bookstore import models
      book = models.Book.object.get(id=1)
      print(book.title)
                 

修改資料記錄

  1. 修改單個實體的某些字段值
      • 通過 get() 得到要修改的實體對象
      • 通過 對象.屬性 的方式修改資料
    1. 儲存
      • 通過 對象.save() 儲存資料
    2. 如下:
      from bookstore import models
      abook = models.Book.objects.get(id=10)
      abook.market_price = "10.5"
      abook.save()
                 
  2. 通過 QuerySet 批量修改 對應的全部字段
    • 直接調用QuerySet的update(屬性=值) 實作批量修改
    • 如:
      # 将 id大于3的所有圖書價格定為0元
      books = Book.objects.filter(id__gt=3)
      books.update(price=0)
      # 将所有書的零售價定為100元
      books = Book.objects.all()
      books.update(market_price=100)
                 

删除記錄

  • 删除記錄是指删除資料庫中的一條或多條記錄
  • 删除單個Entry對象或删除一個查詢結果集(QuerySet)中的全部對象都是調用 delete()方法
  1. 删除單個對象
    • 步驟
      1. 查找查詢結果對應的一個資料對象
      2. 調用這個資料對象的delete()方法實作删除
    • 示例:
      try:
          auth = Author.objects.get(id=1)
          auth.delete()
      except:
          print(删除失敗)
                 
  2. 删除查詢結果集
    • 步驟
      1. 查找查詢結果集中滿足條件的全部QuerySet查詢集合對象
      2. 調用查詢集合對象的delete()方法實作删除
    • 示例:
      # 删除全部作者中,年齡大于65的全部資訊
      auths = Author.objects.filter(age__gt=65)
      auths.delete()
                 

聚合查詢

  • 聚合查詢是指對一個資料表中的一個字段的資料進行部分或全部進行統計查詢,查bookstore_book資料表中的全部書的平均價格,查詢所有書的總個數等,都要使用聚合查詢
  1. 不帶分組聚合
    • 不帶分組的聚合查詢是指導将全部資料進行集中統計查詢
    • 聚合函數:
      • 定義子產品:

        django.db.models

      • 用法:

        from django.db.models import *

      • 聚合函數:
        • Sum, Avg, Count, Max, Min
    • 文法:
      • Entry.objects.aggregate(結果變量名=聚合函數(‘列’))
    • 傳回結果:
      • 由 結果變量名和值組成的字典
      • 格式為:
        • `{“結果變量名”: 值}
    • 示例:
      # 得到所有書的平均價格
      from bookstore import models
      from django.db.models import Count
      result = models.Book.objects.aggregate(myAvg=Avg('price'))
      print("平均價格是:", result['myAvg'])
      print("result=", result)  # {"myAvg": 58.2}
      
      # 得到資料表裡有多少本書
      from django.db.models import Count
      result = models.Book.objects.aggregate(mycnt=Count('title'))
      print("資料記錄總個數是:", result['mycnt'])
      print("result=", result)  # {"mycnt": 10}
      
                 
  2. 分組聚合
    • 分組聚合是指通過計算查詢結果中每一個對象所關聯的對象集合,進而得出總計值(也可以是平均值或總和),即為查詢集的每一項生成聚合。
    • 文法:
      • QuerySet.annotate(結果變量名=聚合函數(‘列’))
    • 用法步驟:
      1. 通過先用查詢結果Entry.object.value. 查找查詢要分組聚合的列
        • Entry.object.value(‘列1’, ‘列2’)
        • 如:
          pub_set = models.Book.objects.values('pub')
          print(books)  # <QuerySet [{'pub': '清華大學出版社'}, {'pub': '清華大學出版社'}, {'pub_hou {'pub': '機械工業出版社'}, {'pub': '清華大學出版社'}]>
          
                     
      2. 通過傳回結果的 QuerySet.annotate 方法分組聚合得到分組結果
        • QuerySet.annotate(名=聚合函數(‘列’))
        • 傳回 QuerySet 結果集,内部存儲結果的字典
        • 如:
          pub_count_set = pub_set.annotate(myCount=Count('pub'))
          print(pub_count_set)  # <QuerySet [{'pub': '清華大學出版社', 'myCount': 7}, {'pub': '機械工業出版社', 'myCount': 3}]>
                     
      • .values(‘查詢列名’)
    • 示例:
      • 得到哪兒個出版社共出版多少本書
      def test_annotate(request):
         - from django.db.models import Count
          from . import models
      
          # 得到所有出版社的查詢集合QuerySet
          pub_set = models.Book.objects.values('pub')
          # 根據出版社查詢分組,出版社和Count的分組聚合查詢集合
          pub_count_set = pub_set.annotate(myCount=Count('pub'))  # 傳回查詢集合
          for item in pub_count_set:
              print("出版社:", item['pub'], "圖書有:", item['myCount'])
          return HttpResponse('請檢視伺服器端控制台擷取結果')
                 

F對象

  • 一個F對象代表資料庫中某個字段的資訊
  • F對象通常是對資料庫中的字段值在不加載到記憶體中的情況下直接在資料庫伺服器端進行操作
  • F對象在 資料包 django.db.models 中.使用時需要通過如下語句進行加載
    • from django.db.models import F

  1. 作用:
    • 在執行過程中擷取某列的值并對其直接進行操作
    • 當同時對資料庫中兩個字段的值進行比較擷取 QuerySet 資料集時,可以便用F對象
  2. 說明:
    • 一個 F()對象代表了一個model的字段的值
  3. 使用它就可以直接參考model的field和執行資料庫操作而不用再把它們(model field)查詢出來放到python記憶體中。
  4. 文法:
    from django.db.models import F
    F('列名')
               
  5. 示例1
    • 更新Book執行個體中所有的制場價漲10元
    models.Book.objects.all().update(market_price=F('market_price')+10)
    # 以下做法好于如下代碼
    books = models.Book.objects.all()
    for book in books:
        book.update(market_price=book.marget_price+10)
        book.save()
               
  6. 示例2
    • 對資料庫中兩個字段的值進行比較,列出哪兒些書的零售價高于定價?
    from django.db.models import F
    from bookstore import models
    books = models.Book.objects.filter(market_price__gt=F('price'))
    for book in books:
        print(book.title, '定價:', book.price, '現價:', book.market_price)
               

Q對象 - Q()

  • 當在擷取查詢結果集 使用複雜的邏輯或

    |

    、 邏輯非

    ~

    等操作時可以借助于 Q對象進行操作
  • 如: 想找出定價低于20元 或 清華大學出版社的全部書,可以寫成
    models.Book.objects.filter(Q(price__lt=20)|Q(pub="清華大學出版社"))
               
  • Q對象在 資料包 django.db.models 中。需要先導入再使用
    • from django.db.models import F

  1. 作用
    • 在條件中用來實作除 and(&) 以外的 or(|) 或 not(~) 操作
  2. 運算符:
    • & 與操作
    • | 或操作
    • 〜 非操作
  3. 文法
    from django.db.models import Q
    Q(條件1)|Q(條件2)  # 條件1成立或條件2成立
    Q(條件1)&Q(條件2)  # 條件1和條件2同時成立
    Q(條件1)&~Q(條件2)  # 條件1成立且條件2不成立
    ...
               
  4. 示例
    from django.db.models import Q
    # 查找清華大學出版社的書或價格低于50的書
    models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清華大學出版社'))
    # 查找不是機械工業出版社的書且價格低于50的書
    models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='機械工業出版社'))