昨日內容回顧
{{ 使用變量的時候 }}
{% 跟邏輯相關的時候 %}
# 模板標簽也會自動補全
# 使用場景:在混合開發的項目中
{% extends 'home.html' %} # 導入指定文件內全部代碼內容
{% block content %}
{% endblock %}
{% block css %}
{% endblock %}
{% block js %}
{% endblock %}
# 模板導入
'''被導入的頁面一般是一個局部頁面''''
{% include 'menu.html' %}
直接cv manage.py中的前4行,放到tests.py中,在加兩句話:
import django
django.setup()
# 測試環境的代碼不一定非要放在tests.py中, 放在任意目錄下即可
1. all
2. first()
3. last()
4. filter => where
5. get
6. values # 返回的結果是列表套字典
7. values_list # 列表套元組
8. order_by() # 默認是升序,字段前面加負號-就是降序,也支持多個字段排序
9. distinct # 不能加主鍵,有unique的也沒有意義
10. exclude
11. exists
12. reverse
# 補充索引的分類:
1. 索引加快查詢速度
2. 分類:
2.1 主鍵索引
2.2 唯一索引
2.3 普通索引 create index()
2.4 聯合索引,組合索引
a b c # index(a, b, c)
走索引的情況(最左匹配原則):a, ab, abc
不走的情況:b, c bc, ac
eg:
where b=1 and c=2
# explain select *from t1
1. gt gte
2. lt lte
3. range => between and
4. in
5. containers
6. startwith
7. endswith
8. __year
9. __month
今日內容概要
- 外鍵字段的增刪改查
- 正反向查詢的概念
- 基于對象的跨表查詢(子查詢)
- 基于雙下劃綫的跨表查詢(連表操作)
- F與Q查詢
- 聚合查詢和分組查詢
內容詳細
1. 數據表準備
# 前期數據表準備
# 以圖書 出版社 作者 作者詳情表為例
# 1.在models.py文件中創建表:
# 書籍表
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
'''
auto_now=False,
如果設置為True, 在更新當前記錄的數據時候,會自動更新時間
auto_now_add=False,
如果設置為True,當插入數據的時候,會把當前時間自動添加進去
'''
# publish_time = models.DateField
publish_time = models.DateTimeField(auto_now=True)
publish = models.ForeignKey(to='Publish')
authors = models.ManyToManyField(to='Author')
# 查詢時返回表頭
def __str__(self):
return self.title
# 出版社表
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
# 作者表
class Author(models.Model):
name = models.CharField(max_length=32)
author_detail = models.OneToOneField(to='AuthorDetail')
# 查詢時返回名稱
def __str__(self):
return self.name
# 作者詳情表
class AuthorDetail(models.Model):
phone = models.CharField(max_length=32)
# 2.在任一init.py文件中寫入:
import pymysql
pymysql.install_as_MySQLdb()
# 3.在settings.py文件中 更改配置連接數據庫:
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# },
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day07', # 數據庫名 自己先用 navicat創建
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123',
'CHARSET': 'utf8'
}
}
# 4.在test.py文件中創建測試環境:
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite6.settings")
import django
django.setup()
from app01 import models
# 代碼寫在此處下面

2. 外鍵字段的增刪改查
# 先自定義出版社 再添加圖書
# 在 test.py文件中測試:
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite6.settings")
import django
django.setup()
from app01 import models
# 代碼寫在此處下面
# 針對一對多 一對一
# 1.增加數據 增加一本書
# 方式一
# models.Book.objects.create(title='西游記', price=100, publish_time='2022.3.3', publish_id=1)
# 方式二
# 先查詢出你要添加的出版社對象
# publish_obj = models.Publish.objects.filter(pk=2).first()
# models.Book.objects.create(title='西游記1', price=111, publish_time='2022-02-01', publish=publish_obj)
# 2.改
# 將主鍵id為1的出版社id改為2
# models.Book.objects.filter(pk=1).update(publish_id=2)
# 改回去
# publish_obj = models.Publish.objects.filter(pk=1).first()
# models.Book.objects.filter(pk=1).update(publish=publish_obj)
# 針對多對多字段操作
# 1.增
# 給一本書添加多個作者
# book_obj = models.Book.objects.filter(pk=1).first()
# 增加
# book_obj.authors # 代表已經到第三張表了
# book_obj.authors.add(1)
# book_obj.authors.add(1, 2)
# 支持對象
# author_obj1 = models.Author.objects.filter(pk=1).first()
# author_obj2 = models.Author.objects.filter(pk=2).first()
# book_obj.authors.add(author_obj1, author_obj2)
# 2.改
# book_obj.authors.set([3, 2])
# author_obj1 = models.Author.objects.filter(pk=1).first()
# author_obj2 = models.Author.objects.filter(pk=2).first()
# book_obj.authors.set([author_obj1, author_obj2])
# 3.刪除
# book_obj = models.Book.objects.filter(pk=2).first()
# book_obj.authors.remove(1)
# book_obj.authors.remove(1,2)
# author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# book_obj.authors.remove(author_obj)
# book_obj.authors.remove(author_obj, author_obj1)
"""
remove
在第三張關系表中刪除數據
括號內既可以傳主鍵字段也可以傳數據對象 并且都支持傳多個
"""
# 清空
# book_obj = models.Book.objects.filter(pk=2).first()
# book_obj.authors.clear() # 清空當前書籍與作者的所有綁定關系
"""
clear
在第三張關系表中清空數據
括號內無需傳值
"""



3. 正反向查詢
# 正向查詢
書籍對象查出版社對象 外鍵字段在書表中 # 正向查詢
書籍對象查作者對象 外鍵字段在書表中 # 正向查詢
作者對象查作者詳情 外鍵字段在作者中 # 正向查詢
# 反向查詢
出版社查書籍對象 外鍵字段不在出版社表中 # 反向查詢
作者查書籍對象 外鍵字段不在作者表中 # 反向查詢
作者詳情查作者 外鍵字段不在作者詳情表中 # 反向查詢
'''
外鍵字段在我手上,我查你就是正向
外鍵字段不再我手上,我查你就是反向
'''
# 口訣:
正向查詢按外鍵字段 ...
反向查詢按表名小寫 或 +_set ...
4. 基于對象的跨表查詢(子查詢)
"""將一條SQL語句的查詢結果當做另外一條SQL語句的查詢條件"""
'''基于對象的跨表查詢'''
# 在 test.py文件中測試:
# 1.查詢書籍主鍵為1的出版社
# 書 >>> 出版社 >>> 正向
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj) # 西游記
# print(book_obj.publish) # Publish object 代表的是出版社對象
# print(book_obj.publish.name) # 北京大學出版社
# print(book_obj.publish.addr) # 北京
# 2.查詢書籍主鍵位1的作者
# book >>> author >>> 正向
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.authors) # app01.Author.None
# print(book_obj.authors.all()) # <QuerySet [<Author: beijing>, <Author: qinghua>]>
# for author_obj in book_obj.authors.all():
# print(author_obj.name) # beijing qinghua
# 3.查詢 qinghua 的手機號
# 作者 >>> 作者詳情 >>> 正向
# author_obj = models.Author.objects.filter(name='qinghua').first()
# print(author_obj.author_detail) # AuthorDetail object 結果時對象
# print(author_obj.author_detail.phone) # 120
# 4.查詢武漢出版社出版的書籍
# 出版社查書 >>> 反向
# publish_obj = models.Publish.objects.filter(name='武漢大學出版社').first()
# print(publish_obj.book_set) # app01.Book.None
# print(publish_obj.book_set.all()) # <QuerySet [<Book: 紅樓夢>]>
# for book_obj in publish_obj.book_set.all():
# print(book_obj.title) # 紅樓夢
# 5.查詢 qinghua 寫過的書
# 作者查書 >>> 反向
# author_obj = models.Author.objects.filter(name='qinghua').first()
# print(author_obj.book_set.all()) # <QuerySet [<Book: 西游記1>]>
# 6.查詢手機號是120的作者姓名
# 作者詳情查作者信息 >>> 反向
# author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
# print(author_detail_obj.author) # qinghua
'''
總結:
反向查詢只要查詢出的結果可能有多個的時候,都要加上 表名_set.all()
如果查詢出來的結果是一個,就不用加_set,直接使用表名小寫
'''


5. 基于雙下劃線的跨表查詢
"""正反向查詢的概念同樣適用"""
# 在 test.py文件中測試:
# 1.查詢書籍主鍵為1的出版社名稱與書籍名稱
# 正向
# res = models.Book.objects.filter(pk=1).values('title', 'publish__name')
# print(res) # <QuerySet [{'title': '西游記', 'publish__name': '北京大學出版社'}]>
# 2.查詢書籍主鍵位1的作者
# 正向
# res = models.Book.objects.filter(pk=1).values('authors__name')
# print(res) # <QuerySet [{'authors__name': 'beijing'}]>
# 3.查詢作者 qinghua 的手機號
# 正向
# res = models.Author.objects.filter(name='qinghua').values('author_detail__phone')
# print(res) # <QuerySet [{'author_detail__phone': '120'}]>
# 4.查詢 武漢大學出版社 出版的書籍名稱
# 反向
# res = models.Publish.objects.filter(name='武漢大學出版社').values('book__title')
# print(res) # <QuerySet [{'book__title': '紅樓夢'}]>
# 5.查詢 qinghua 寫過的書
# 反向
# res = models.Author.objects.filter(name='qinghua').values('book__title')
# print(res) # <QuerySet [{'book__title': '西游記1'}]>
# 6.查詢手機號是120的作者姓名
# 反向
# res = models.AuthorDetail.objects.filter(phone=120).values('author__name')
# print(res) # <QuerySet [{'author__name': 'qinghua'}]>
# 7.查詢書籍主鍵位1的作者的手機號
# 正向
# book author author_detail
# res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
# print(res) # <QuerySet [{'authors__author_detail__phone': '110'}]>
6. F查詢和Q查詢
# F查詢
可以拿到數據庫中原有的數據
from django.db.models import F
''' F查詢默認是對數字類型的'''
# 1.把書籍的價格在原來的基礎之上加100元
# SQL語句:
# update book set price = price + 100 where id=1;
'''
一般來說,跟數據相關的模塊要么在django.db,要么在django.db.models
'''
# models.Book.objects.update(price=F('price')+100)
# 2.F查詢對 字符類型的
from django.db.models.functions import Concat
from django.db.models import Value
# models.Book.objects.update(title=Concat(F('title'), Value('南京出版社')))
# Q查詢
# 查詢書籍價格大于等于300的或者id=1的數據
# sql: select * from t where price >= 300 or id=1
# orm:
from django.db.models import Q
# res = models.Book.objects.filter(Q(price__gte=300), Q(id=1)) # 逗號分隔,是and關系
# res = models.Book.objects.filter(Q(price__gte=300) | Q(id=1)) # |分隔,是or關系
# res = models.Book.objects.filter(~Q(price__gte=300) | ~Q(id=1)) # ~分隔,取反
# print(res)
