Django web 框架學習之旅(3)

《Django Web 框架》

目錄

靜態文件

  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;
      create database mywebdb default charset utf8 ;
      
    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
      • 作用:表示不定長的字符數據

字段選項

  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)
# 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='機械工業出版社'))
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章