1. 程式人生 > 其它 >7、Django框架進階1-- 圖書相關表關係建立、基於雙下劃線跨表查詢、聚合查詢、F查詢、Q查詢、django的admin使用、使用指令碼呼叫django(django測試環境)、django檢視原生sql兩種方式

7、Django框架進階1-- 圖書相關表關係建立、基於雙下劃線跨表查詢、聚合查詢、F查詢、Q查詢、django的admin使用、使用指令碼呼叫django(django測試環境)、django檢視原生sql兩種方式

1 圖書相關表關係建立

1 5個表
2 書籍表,作者表,作者詳情表,出版社表,書籍和作者表(多對多關係)

3 一對一的關係,關聯欄位可以寫在任意一方
4 一對多的關係,關聯欄位寫在多的一方
5 多對多的關係,必須建立第三張表(orm中,可以用一個欄位表示,這個欄位可以寫在任意一方)


5 把表關係同步到資料庫中
   -python3 manage.py makemigrations # 在migrations資料夾下記錄一下
   -python3 manage.py migrate      # 把記錄變更到資料庫

6 表關係
from django.db import models

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()  # 本質是varchar型別

class Book(models.Model):
    nid = models.AutoField(primary_key=True) # 自增,主鍵
    name = models.CharField(max_length=32)   # varchar  32
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()  # 年月日型別
    # 閱讀數
    # reat_num=models.IntegerField(default=0)
    # 評論數
    # commit_num=models.IntegerField(default=0)
    # 建議加引號,也可以不加引號
    #models.CASCADE:級聯刪除,設為預設值,設為空,設為指定的值,不做處理
    # 2.x以後必須加,否則報錯
    # publish = models.ForeignKey(to=Publish,to_field='nid',on_delete=models.CASCADE)
    publish = models.ForeignKey(to=Publish,to_field='nid',on_delete=models.CASCADE)

    # 在資料庫中,根本沒有這個欄位,orm用來查中介模型詢,對映成一個表了
    # 如果我不這麼寫,手動建立第三張表,
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)
    # author_detail = models.ForeignKey(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)

2基於雙下劃線的跨表查詢

1 基於物件的跨表查
	-子查詢,多次查詢
2 基於雙下劃線的跨表查
	-多表連線查詢

import os
#載入配置檔案,跑django的專案,最開始就是把配置檔案載入上
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")

if __name__ == '__main__':
    import django  # 安裝了django模組,就可以import
    django.setup() # 使用環境變數中的配置檔案,跑django

    from app01 import models

    # 正反向:正向,關聯欄位在當前物件中,去另一個表中查

    # 查詢主鍵為1的書籍的出版社所在的城市
    # book=models.Book.objects.filter(pk=1).first()
    # print(book.publish.city)

    # res=models.Book.objects.filter(pk=1).values('publish__city')
    # print(res)

    # res=models.Publish.objects.filter(book__nid=1).values('city')
    # print(res)


    # 查詢所有住址在北京的作者的姓名

    # res=models.Author.objects.filter(author_detail__addr='北京').values('name')
    # print(res)
    #
    # res=models.AuthorDatail.objects.filter(addr='北京').values('author__name')
    # print(res)


    #查詢egon出過的所有書籍的名字

    # res=models.Author.objects.filter(name='egon').values('book__name')
    # print(res)
    # res=models.Book.objects.filter(authors__name='egon').values('name')
    # print(res)

    # 查詢人民出版社出版過的所有書籍的名字以及作者的姓名和地址

    res=models.Book.objects.filter(publish__name='北京出版社')\
        .values('publish__name','name','authors__name','authors__author_detail__addr')

    res=models.Publish.objects.filter(name='北京出版社').values('name','book__name','book__authors__name','book__authors__author_detail__addr')

    res=models.Author.objects.filter(book__publish__name='北京出版社').values('book__publish__name','book__name','name','author_detail__addr')

    res=models.AuthorDatail.objects.filter(author__book__publish__name='北京出版社').values('author__book__publish__name','author__book__name','author__name','addr')
    print(res)

3 聚合查詢

1 聚合函式,sum,max,min,count,avg
2 把聚合結果欄位重新命名
res=models.Book.objects.all().aggregate(aaa=Sum('price'))
# 聚合查詢# 計算所有圖書的平均價格from django.db.models import Sum,Avg,Max,Min,Countres=models.Book.objects.all().aggregate(Avg('price'))print(res)# 計算所有圖書的最高價格res=models.Book.objects.all().aggregate(Max('price'))print(res)# 計算所有圖書的總價格res=models.Book.objects.all().aggregate(Sum('price'))print(res)# egon出版圖書的總價格# 北京出版從出版社書的最高價格

# 計算所有圖書的總價格
   res=models.Book.objects.all().aggregate(book_sum=Sum('price'),book_avg=Avg('price'))
    print(res)

4F查詢

    # F 查詢,取出某個欄位對應的值
    from django.db.models import F
    #查詢評論數大於閱讀數的書籍
    # res=models.Book.objects.filter(commit_num__gt=F('read_num'))
    # print(res)

    # 把所有圖書價格+1

    res=models.Book.objects.all().update(price=F('price')+1)
    print(res) # 影響額行數

5 Q查詢

    # Q查詢:構造出與&    或|   非~
    from django.db.models import Q

    # 查詢名字叫紅樓夢或者價格大於100的書
    # res=models.Book.objects.filter(name='紅樓夢',price__gt=100)
    # res=models.Book.objects.filter(Q(name='紅樓夢')|Q(price__gt=100))
    # res=models.Book.objects.filter(Q(name='紅樓夢')& Q(price__gt=100))

    # 查詢名字不是紅樓夢的書

    res=models.Book.objects.filter(~Q(name='紅樓夢'))
    #查詢名字不是紅樓夢,並且價格大於100的書
    # res = models.Book.objects.filter(~Q(name='紅樓夢'),price__gt='100')
    res = models.Book.objects.filter(~Q(name='紅樓夢')&Q(price__gt='100'))
    print(res)

補充:

1 普通函式以__開頭
	-說明當前函式只在當前模組(py)下使用,儘量不在外部呼叫
    
2 mysql
	-utf8:2個位元組表示一個字元
	-utf8mb4:等同於真正意義上的utf-8
   	-utf-8:1--4個位元組,表示一個字元
    
3 django 的orm使用pymysql連線mysql
	-需要加這一句話(本質就是猴子補丁的應用)
    	import pymysql
		pymysql.install_as_MySQLdb()
   -本質是想讓它執行,放在哪都可以
		-init中
    	-settings.py中

djago admin的使用

1 後臺管理,方便我們快速的錄入書籍
2 使用方法:
	第一步:在admin.py 中把要使用的表註冊
    	 from app01 import models
        admin.site.register(models.Book)
        admin.site.register(models.Author)
        admin.site.register(models.AuthorDatail)
        admin.site.register(models.Publish)
   第二步:建立個超級管理員
		python3 manage.py createsuperuser 
    	輸入使用者名稱,輸入密碼
        
   第三步:登入,錄入書籍
		-http://127.0.0.1:8000/admin/
		

使用指令碼呼叫django

1 寫一個指令碼檔案
import os
#載入配置檔案,跑django的專案,最開始就是把配置檔案載入上
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")

if __name__ == '__main__':
    import django  # 安裝了django模組,就可以import
    django.setup() # 使用環境變數中的配置檔案,跑django

    from app01 import models

django檢視原生sql

1 queryset物件.query
2 通過日誌,如下,配置到setting.py中
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}