models模型層環境配置和表查詢

通常操做

在進行通常操做時先配置一下參數,使得咱們能夠直接在Django頁面中運行咱們的測試腳本python

在Python腳本中調用Django環境

模型轉爲mysql數據庫中的表settings配置

須要在settings中配置:mysql

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'tabledatabase',
        'USER':'root',
        'PASSWORD':'root',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'CHARSET':'utf8',
        'ATOMIC_REQUEST': True,
        'OPTIONS': {
            "init_command": "SET storage_engine=MyISAM",
        }
    }
}
'''
'NAME':要鏈接的數據庫,鏈接前須要建立好
'USER':鏈接數據庫的用戶名
'PASSWORD':鏈接數據庫的密碼
'HOST':鏈接主機,默認本機
'PORT':端口 默認3306
'CHARSET':'utf8',字符編碼默認utf8
'ATOMIC_REQUEST': True,
設置爲True統一個http請求對應的全部sql都放在一個事務中執行(要麼全部都成功,要麼全部都失敗)。
是全局性的配置, 若是要對某個http請求放水(而後自定義事務),能夠用non_atomic_requests修飾器 
'OPTIONS': {
             "init_command": "SET storage_engine=MyISAM",
            }
設置建立表的存儲引擎爲MyISAM,INNODB
'''

注意1:NAME即數據庫的名字,在mysql鏈接前該數據庫必須已經建立,而上面的sqlite數據庫下的db.sqlite3則是項目自動建立 USER和PASSWORD分別是數據庫的用戶名和密碼。設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。而後,啓動項目,會報錯:no module named MySQLdb 。這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb 對於py3有很大問題,因此咱們須要的驅動是PyMySQL 因此,咱們只須要找到項目名文件下的__init__,在裏面寫入:linux

import pymysql
pymysql.install_as_MySQLdb()

最後經過兩條數據庫遷移命令便可在指定的數據庫中建立表 :git

python manage.py makemigrations
python manage.py migrate

注意2:確保配置文件中的INSTALLED_APPS中寫入咱們建立的app名稱sql

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "app01"
]

注意3:若是報錯以下:數據庫

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

MySQLclient目前只支持到python3.4,所以若是使用的更高版本的python,須要修改以下:django

經過查找路徑C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql
這個路徑裏的文件把session

if version < (1, 3, 3):
     raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

註釋掉就能夠了app

測試文件tests.py的使用和配置

img

import os
if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "untitled15.settings")
    import django
    django.setup()

    from app01 import models

    books = models.Book.objects.all()
    print(books)

這樣就能夠直接運行你的test.py文件來運行測試測試

Django終端打印SQL語句settings中配置

若是你想知道你對數據庫進行操做時,Django內部究竟是怎麼執行它的sql語句時能夠加下面的配置來查看

在Django項目的settings.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',
        },
    }
}

配置好以後,再執行任何對數據庫進行操做的語句時,會自動將Django執行的sql語句打印到pycharm終端上

補充:

除了配置外,還能夠經過一點.query便可查看查詢語句,具體操做以下:

img

單表的數據準備

操做下面的操做以前,咱們實現建立好了數據表,這裏主要演示下面的操做,再也不細講建立準備過程

python manage.py makemigrations
python manage.py migrate
.models.py
from django.db import models

# Create your models here.
from django.db import models


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_data = models.DateField()

    def __str__(self):
        return self.title
tests.py
import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "onetable.settings")
    import django

    django.setup()

單表操做增刪改

from oneapp import models
import datetime

增長
res = models.Book.objects.create(title='python',price=121,publish_data=datetime.datetime.now())
print(res)
res1 = models.Book.objects.create(title='python',price=121,publish_data='2019-5-4')
print(res1)
book_obj = models.Book(title='math',price=120,publish_data='2019-4-7')

book_obj.save()
刪除
res = models.Book.objects.filter(title='python').delete()
print(res)
修改
res = models.Book.objects.filter(pk=3).update(title='linux')
print(res)
book_obj= models.Book.objects.filter(pk=5).first()
book_obj.title = 'Go'
book_obj.save()

必知必會單表查詢13條

<1> all(): 查詢全部結果

1
    res = models.Book.objects.all()
    print(res)

**<2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對象**

2
 res = models.Book.objects.filter()
    print(res)
    res = models.Book.objects.filter(title='python')
    print(res.first().price)

**<3> get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。**

3
    res = models.Book.objects.get(title='python')
    print(res)

**<4> exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象**

4
    res = models.Book.objects.exclude(id=4)
    print(res)

<5> values(*field): 返回一個ValueQuerySet——一個特殊的

QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列

5
    res = models.Book.objects.values('title')
    print(res)

<6> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列

6
    res = models.Book.objects.values_list('title')
    print(res,type(res.first()))

<7> order_by(*field): 對查詢結果排序

7
    res = models.Book.objects.order_by('price')#默認是升序
    print(res)
    res = models.Book.objects.order_by('-price')
    print(res)

<8> reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。不能傳值

8
    print(models.Book.objects.order_by('price'))
    res = models.Book.objects.order_by('price').reverse()
    print(res)

<9> distinct(): 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。)不能傳值

9
    res = models.Book.objects.all().distinct()
    print(res)

<10> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。不能傳值

10
    res = models.Book.objects.all().count()
    print(res)

<11> first(): 返回第一條記錄

11
    res = models.Book.objects.all().first()
    print(res)

<12> last(): 返回最後一條記錄

12
    res = models.Book.objects.all().last()
    print(res)

<13> exists(): 若是QuerySet包含數據,就返回True,不然返回False,不能傳值

13
    res = models.Book.objects.all().exists()
    print(res)

13個必會單表操做方法總結

返回QuerySet對象的方法有

all()查詢全部結果

filter()它包含了與所給篩選條件相匹配的對象,不加條件的時候返回全部。和all()相同。

exclude()它包含了與所給篩選條件不匹配的對象

order_by()對查詢結果排序('-id')

reverse()對查詢結果反向排序,對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。

distinct()從返回結果中剔除重複紀錄

特殊的QuerySet

values() 返回一個可迭代的字典序列,返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列,獲取全部的值,以字典的形式打印

values_list() 返回一個可迭代的元祖序列,它與values()很是類似,它返回的是一個元組序列。

返回具體對象的

get() 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。

first() 返回第一條記錄

last()返回最後一條記錄

返回數字的方法有

count()返回數據庫中匹配查詢(QuerySet)的對象數量。

返回布爾值的方法有:

exists()若是QuerySet包含數據,就返回True,不然返回False

不能傳值的有

count(),first(),last(),exists(),distinct(),all()

單表查詢之神奇的雙下劃線 

查詢價格大於200的書籍
res = models.Book.objects.filter(price__gt=200)
查詢價格小於200的書籍
res = models.Book.objects.filter(price__lt=200)
查詢價格大於或者等於200的書籍
res = models.Book.objects.filter(price__gte=200)
res1 = models.Book.objects.filter(price__lte=200)

價格是200 或者是123.23 或者666.66
res = models.Book.objects.filter(price__in=[200,123.23,666.66])
價格在200 到700之間的書籍
res = models.Book.objects.filter(price__range=(200,666.66))# 顧頭不顧尾
res = models.Book.objects.filter(price__range=[10, 200])

模糊匹配

# 模糊匹配
"""
like
    %
    _
"""
查詢書籍名稱中包含p的
res = models.Book.objects.filter(title__contains='p')  # 區分大小寫
忽略大小寫
res = models.Book.objects.filter(title__icontains='p')  # 忽略大小寫


查詢書籍名稱是以三開頭的書籍
res = models.Book.objects.filter(title__startswith='p')
res1 = models.Book.objects.filter(title__endswith='h')
print(res1)


查詢出版日期是2019年的書籍
res = models.Book.objects.filter(publish_date__year='2019')
查詢出版日期是10月的書籍
res = models.Book.objects.filter(publish_date__month='10')

date時間操做

Book.objects.filter(pub_date__year=2012)
date字段還能夠:
models.Book.objects.filter(first_day__year=2017)
date字段能夠經過在其後加__year,__month,__day等來獲取date的特色部分數據
# date
    # Book.objects.filter(pub_date__date=datetime.date(2005, 1, 1))

    # Book.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
    # year
    #
    # Book.objects.filter(pub_date__year=2005)
    # Book.objects.filter(pub_date__year__gte=2005)

    # month
    #
    # Book.objects.filter(pub_date__month=12)
    # Book.objects.filter(pub_date__month__gte=6)

    # day
    #
    # Book.objects.filter(pub_date__day=3)
    # Book.objects.filter(pub_date__day__gte=3)

    # week_day
    #
    # Book.objects.filter(pub_date__week_day=2)
    # Book.objects.filter(pub_date__week_day__gte=2)
須要注意的是在表示一年的時間的時候,咱們一般用52周來表示,由於天數是不肯定的,老外就是按周來計算薪資的哦~

ForeignKey操做

正向查找(兩種方式)

1.對象查找(跨表)

語法:

對象.關聯字段.字段

要點:先拿到對象,再經過對象去查對應的外鍵字段,分兩步

示例:

book_obj = models.Book.objects.first()  # 第一本書對象(第一步)
print(book_obj.publisher)  # 獲得這本書關聯的出版社對象
print(book_obj.publisher.name)  # 獲得出版社對象的名稱

2.字段查找(跨表)

語法:

關聯字段**__****字段**

要點:利用Django給咱們提供的神奇的雙下劃線查找方式

示例:

models.Book.objects.all().values("publisher__name")
#拿到全部數據對應的出版社的名字,神奇的下劃線幫咱們誇表查詢

反向操做(兩種方式)

1.對象查找

語法:

obj.表名_set

要點:先拿到外鍵關聯多對一,一中的某個對象,因爲外鍵字段設置在多的一方,因此這裏仍是借用Django提供的雙下劃線來查找

示例:

publisher_obj = models.Publisher.objects.first()  # 找到第一個出版社對象
books = publisher_obj.book_set.all()  # 找到第一個出版社出版的全部書
titles = books.values_list("title")  # 找到第一個出版社出版的全部書的書名

結論:若是想經過一的那一方去查找多的一方,因爲外鍵字段不在一這一方,因此用__set來查找便可

2.字段查找

語法:

**表名__字段**

要點:直接利用雙下滑線完成誇表操做

titles = models.Publisher.objects.values("book__title")

ManyToManyField

class RelatedManager

"關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器。

它存在於下面兩種狀況:

  1. 外鍵關係的反向查詢
  2. 多對多關聯關係

簡單來講就是在多對多表關係而且這一張多對多的關係表是有Django自動幫你建的狀況下,下面的方法纔可以使用。

方法,add(),set(),remove(),clear()

create()

建立一個關聯對象,並自動寫入數據庫,且在第三張雙方的關聯表中自動新建上雙方對應關係。

models.Author.objects.first().book_set.create(title="偷塔祕籍")
上面這一句幹了哪些事兒:
1.由做者表中的一個對象跨到書籍比表
2.新增名爲偷塔祕籍的書籍並保存
3.到做者與書籍的第三張表中新增二者之間的多對多關係並保存

add()

add() 括號內既能夠傳數字也能夠傳數據對象,而且都支持傳多個

把指定的model對象添加到第三張關聯表中。

添加對象,添加id

book_obj = models.Book.objects.filter(pk=3).first()
print(book_obj.authors)  # 就至關於 已經在書籍和做者的關係表了
book_obj.authors.add(1)
book_obj.authors.add(2,3)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1)

set()

set() 括號內 既能夠傳數字也傳對象
而且也是支持傳多個的
可是須要注意 括號內必須是一個可迭代對象

更新某個對象在第三張表中的關聯對象。不一樣於上面的add是添加,set至關於重置,能夠添加對象和id

book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.set([3,])
book_obj.authors.set([1,3])
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj,))
book_obj.authors.set((author_obj,author_obj1))

remove()

remove() 括號內 既能夠傳數字也傳對象 而且也是支持傳多個的

從關聯對象集中移除執行的model對象(移除對象在第三張表中與某個關聯對象的關係)

book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.remove(2)
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)

clear()

clear()括號內不須要傳任何參數 直接清空當前書籍對象全部的記錄

從關聯對象集中移除一切對象。(移除全部與對象相關的關係信息)

book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.clear()

注意:

對於ForeignKey對象,clear()和remove()方法僅在null=True時存在。

舉個例子:

ForeignKey字段沒設置null=True時,

class Book(models.Model):
    title = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Publisher)

沒有clear()和remove()方法:

>>> models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'RelatedManager' object has no attribute 'clear'

當ForeignKey字段設置null=True時,

class Book(models.Model):
    name = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Class, null=True)

此時就有clear()和remove()方法:

>>> models.Publisher.objects.first().book_set.clear()

再次強調:

  1. 對於全部類型的關聯字段,add()、create()、remove()和clear(),set()都會立刻更新數據庫。換句話說,在關聯的任何一端,都不須要再調用save()方法。

實例:咱們來假定下面這些概念,字段和關係

做者模型:一個做者有姓名和年齡。

做者詳細模型:把做者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。做者詳情模型和做者模型之間是一對一的關係(one-to-one)

出版商模型:出版商有名稱,所在城市以及email。

書籍模型: 書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many);一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many)。

注意:關聯字段與外鍵約束沒有必然的聯繫(建管理字段是爲了進行查詢,建約束是爲了避免出現髒數據)

在Models建立以下模型

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=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)

    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    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)


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


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()

注意事項:

  • 表的名稱myapp_modelName,是根據 模型中的元數據自動生成的,也能夠覆寫爲別的名稱  
  • id 字段是自動添加的
  • 對於外鍵字段,Django 會在字段名上添加"_id" 來建立數據庫中的列名
  • 這個例子中的CREATE TABLE SQL 語句使用PostgreSQL 語法格式,要注意的是Django 會根據settings 中指定的數據庫類型來使用相應的SQL 語句。
  • 定義好模型以後,你須要告訴Django _使用_這些模型。你要作的就是修改配置文件中的INSTALL_APPSZ中設置,在其中添加models.py所在應用的名稱。
  • 外鍵字段 ForeignKey 有一個 null=True 的設置(它容許外鍵接受空值 NULL),你能夠賦給它空值 None 。

二 添加表記錄

一對多的

方式1:
   publish_obj=Publish.objects.get(nid=1)
   book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish=publish_obj)
  
方式2:
   book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish_id=1)

核心:book_obj.publish與book_obj.publish_id是什麼?

關鍵點:

    一 book_obj.publish=Publish.objects.filter(id=book_obj.publish_id).first()

    二 book_obj.authors.all()
       關鍵點:book.authors.all()  # 與這本書關聯的做者集合

        1 book.id=3
        2 book_authors
            id  book_id  author_ID
            3      3             1
            4      3             2

        3  author
           id   name
           1   alex
           2   egon

    book_obj.authors.all()    ------->   [alex,egon]
# -----一對多添加
    pub=Publish.objects.create(name='egon出版社',email='445676@qq.com',city='山東')
    print(pub)

    # 爲book表綁定和publish的關係
    import datetime,time
    now=datetime.datetime.now().__str__()
    now = datetime.datetime.now().strftime('%Y-%m-%d')
    print(type(now))
    print(now)
    # 日期類型必須是日期對象或者字符串形式的2018-09-12(2018-9-12),其它形式不行
    Book.objects.create(name='海燕3',price=333.123,publish_date=now,publish_id=2)
    Book.objects.create(name='海3燕3',price=35.123,publish_date='2018/02/28',publish=pub)
    pub=Publish.objects.filter(nid=1).first()
    book=Book.objects.create(name='測試書籍',price=33,publish_date='2018-7-28',publish=pub)
    print(book.publish.name)
    # 查詢出版了紅樓夢這本書出版社的郵箱
    book=Book.objects.filter(name='紅樓夢').first()
    print(book.publish.email)

多對多

# 當前生成的書籍對象
    book_obj=Book.objects.create(title="追風箏的人",price=200,publishDate="2012-11-12",publish_id=1)
    # 爲書籍綁定的作做者對象
    yuan=Author.objects.filter(name="yuan").first() # 在Author表中主鍵爲2的紀錄
    egon=Author.objects.filter(name="alex").first() # 在Author表中主鍵爲1的紀錄

    # 綁定多對多關係,即向關係表book_authors中添加紀錄
    book_obj.authors.add(yuan,egon)    #  將某些特定的 model 對象添加到被關聯對象集合中。   =======    book_obj.authors.add(*[])
book = Book.objects.filter(name='紅樓夢').first()
    egon=Author.objects.filter(name='egon').first()
    lqz=Author.objects.filter(name='lqz').first()
    # 1 沒有返回值,直接傳對象
    book.authors.add(lqz,egon)
    # 2 直接傳做者id
    book.authors.add(1,3)
    # 3 直接傳列表,會打散
    book.authors.add(*[1,2])
    # 解除多對多關係
    book = Book.objects.filter(name='紅樓夢').first()
    # 1 傳做者id
    book.authors.remove(1)
    # 2 傳做者對象
    egon = Author.objects.filter(name='egon').first()
    book.authors.remove(egon)
    #3 傳*列表
    book.authors.remove(*[1,2])
    #4 刪除全部
    book.authors.clear()
    # 5 拿到與 這本書關聯的全部做者,結果是queryset對象,做者列表
    ret=book.authors.all()
    # print(ret)
    # 6 queryset對象,又能夠繼續點(查詢紅樓夢這本書全部做者的名字)
    ret=book.authors.all().values('name')
    print(ret)
    # 以上總結:
    # (1)
    # book=Book.objects.filter(name='紅樓夢').first()
    # print(book)
    # 在點publish的時候,其實就是拿着publish_id又去app01_publish這個表裏查數據了
    # print(book.publish)
    # (2)book.authors.all()

核心:book_obj.authors.all()是什麼?

多對多關係其它經常使用API:

book_obj.authors.remove()      # 將某個特定的對象從被關聯對象集合中去除。    ======   book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被關聯對象集合
book_obj.authors.set()         #先清空再設置 

三 基於對象的跨表查詢

ORM跨表查詢
        1.子查詢
        2.連表查詢
        
    正反向的概念
        外鍵字段在誰那兒 由誰查誰就是正向
        
        誰手裏有外鍵字段 誰就是正向查
        沒有外鍵字段的就是反向
        書籍對象 查  出版社    外鍵字段在書籍       正向查詢
        出版社 查 書籍         外鍵字段在書籍       反向查詢
        
        
        正向查詢按字段
        反向查詢按表名小寫 ...
# 1.基於對象的跨表查詢    子查詢
    # 1.查詢書籍是python入門的出版社名稱
    # book_obj = models.Book.objects.filter(title='python入門').first()
    # # 正向查詢按字段
    # print(book_obj.publish.name)
    # print(book_obj.publish.addr)
    # 2.查詢書籍主鍵是6的做者姓名
    # book_obj = models.Book.objects.filter(pk=6).first()
    # # print(book_obj.authors)  # app01.Author.None
    # print(book_obj.authors.all())
    # 3.查詢做者是jason的手機號
    # author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.author_detail.phone)
    # print(author_obj.author_detail.addr)
    """
    正向查詢 按字段 
    當該字段所對應的數據有多個的時候 須要加.all()
    否者點外鍵字段直接就可以拿到數據對象
    """
    # 4.查詢出版社是東方出版社出版過的書籍
    # publish_obj = models.Publish.objects.filter(name='東方出版社').first()
    # # print(publish_obj.book_set)  # app01.Book.None
    # print(publish_obj.book_set.all())
    # 5.查詢做者是jason寫過的全部的書
    # author_obj = models.Author.objects.filter(name='jason').first()
    # # print(author_obj.book_set)  # app01.Book.None
    # print(author_obj.book_set.all())
    # 6.查詢手機號是110的做者
    # author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    # print(author_detail_obj.author)
    # print(author_detail_obj.author.name)
    # print(author_detail_obj.author.age)
    """
    反向查詢按表名小寫 
        何時須要加_set
            當查詢的結果能夠是多個的狀況下 須要加_set.all()
        何時不須要加_set
            當查詢的結果有且只有一個的狀況下 不須要加任何東西 直接表名小寫便可
    """
    # 7.查詢書籍是python入門的做者的手機號
    # book_obj = models.Book.objects.filter(title='python入門').first()
    # print(book_obj.authors.all())

    # 2.基於雙下劃綫的跨表查詢   連表查詢
    """
    MySQL
        left join
        inner join
        right join
        union
    """
    # 1.查詢書籍是python入門的出版社名稱
    # 正向
    # res = models.Book.objects.filter(title='python入門').values('publish__name')
    # print(res)
    # 反向
    # res = models.Publish.objects.filter(book__title='python入門').values('name')
    # print(res)


    # 2.查詢做者是jason的手機號碼
    # 正向
    # res1 = models.Author.objects.filter(name='jason').values('author_detail__phone')
    # print(res1)
    # 反向
    # res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
    # print(res)



    # 3.查詢手機號是120的做者姓名

    # res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name')
    # print(res2)
    # res = models.Author.objects.filter(author_detail__phone=120).values('name','author_detail__addr')
    # print(res)


    # 4.查詢出版社是東方出版社出版的書籍名稱
    # res = models.Publish.objects.filter(name='東方出版社').values('book__title','addr')
    # print(res)
    # 5.查詢做者是jason的寫過的書的名字和價格
    # res = models.Author.objects.filter(name='jason').values('book__title','book__price')
    # print(res)

    # 7.查詢書籍是python入門的做者的手機號
    # res = models.Book.objects.filter(title='python入門').values('authors__author_detail__phone')
    # print(res)

一對多查詢(publish與book)

正向查詢(按字段:publish)

# 查詢主鍵爲1的書籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主鍵爲1的書籍對象關聯的出版社對象
print(book_obj.publish.city)

反向查詢(按表名:book_set)

publish=Publish.objects.get(name="蘋果出版社")
#publish.book_set.all() : 與蘋果出版社關聯的全部書籍對象集合
book_list=publish.book_set.all()    
for book_obj in book_list:
       print(book_obj.title)
# 一對多正向查詢
    book=Book.objects.filter(name='紅樓夢').first()
    print(book.publish)#與這本書關聯的出版社對象
    print(book.publish.name)
    # 一對多反向查詢
    # 人民出版社出版過的書籍名稱
    pub=Publish.objects.filter(name='人民出版社').first()
    ret=pub.book_set.all()
    print(ret)

一對一查詢(Author 與 AuthorDetail)

正向查詢(按字段:authorDetail):

egon=Author.objects.filter(name="egon").first()
print(egon.authorDetail.telephone)

反向查詢(按表名:author):

# 查詢全部住址在北京的做者的姓名
 
authorDetail_list=AuthorDetail.objects.filter(addr="beijing")
for obj in authorDetail_list:
     print(obj.author.name)
# 一對一正向查詢
    # lqz的手機號
    lqz=Author.objects.filter(name='lqz').first()
    tel=lqz.author_detail.telephone
    print(tel)
    # 一對一反向查詢
    # 地址在北京的做者姓名
    author_detail=AuthorDatail.objects.filter(addr='北京').first()
    name=author_detail.author.name
    print(name)

多對多查詢 (Author 與 Book)

正向查詢(按字段:authors):

# 眉全部做者的名字以及手機號
 
book_obj=Book.objects.filter(title="眉").first()
authors=book_obj.authors.all()
for author_obj in authors:
     print(author_obj.name,author_obj.authorDetail.telephone)

反向查詢(按表名:book_set):

# 查詢egon出過的全部書籍的名字
 
    author_obj=Author.objects.get(name="egon")
    book_list=author_obj.book_set.all()        #與egon做者相關的全部書籍
    for book_obj in book_list:
        print(book_obj.title)
# 正向查詢----查詢紅樓夢全部做者名稱
    book=Book.objects.filter(name='紅樓夢').first()
    ret=book.authors.all()
    print(ret)
    for auth in ret:
        print(auth.name)
    # 反向查詢 查詢lqz這個做者寫的全部書
    author=Author.objects.filter(name='lqz').first()
    ret=author.book_set.all()
    print(ret)

注意:

你能夠經過在 ForeignKey() 和ManyToManyField的定義中設置 related_name 的值來覆寫 FOO_set 的名稱。例如,若是 Article model 中作一下更改:

publish = ForeignKey(Book, related_name='bookList')

那麼接下來就會如咱們看到這般:

# 查詢 人民出版社出版過的全部書籍
 
publish=Publish.objects.get(name="人民出版社")
book_list=publish.bookList.all()  # 與人民出版社關聯的全部書籍對象集合

基於雙下劃線的跨表查詢

Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關係,它能自動確認 SQL JOIN 聯繫。要作跨關係查詢,就使用兩個下劃線來連接模型(model)間關聯字段的名稱,直到最終連接到你想要的model 爲止。

'''
    正向查詢按字段,反向查詢按表名小寫用來告訴ORM引擎join哪張表
'''

一對多查詢

# 練習:  查詢蘋果出版社出版過的全部書籍的名字與價格(一對多)

    # 正向查詢 按字段:publish
queryResult=Book.objects.filter(publish__name="蘋果出版社").values_list("title","price")

    # 反向查詢 按表名:book

queryResult=Publish.objects.filter(name="蘋果出版社").values_list("book__title","book__price")查詢的本質同樣,就是select from的表不同
# 正向查詢按字段,反向查詢按表名小寫
    # 查詢紅樓夢這本書出版社的名字
    # select * from app01_book inner join app01_publish
    # on app01_book.publish_id=app01_publish.nid
    ret=Book.objects.filter(name='紅樓夢').values('publish__name')
    print(ret)
    ret=Publish.objects.filter(book__name='紅樓夢').values('name')
    print(ret)

多對多查詢 

# 練習: 查詢alex出過的全部書籍的名字(多對多)

    # 正向查詢 按字段:authors:
    queryResult=Book.objects.filter(authors__name="yuan").values_list("title")

    # 反向查詢 按表名:book
    queryResult=Author.objects.filter(name="yuan").values_list("book__title","book__price")
# 正向查詢按字段,反向查詢按表名小寫
    # 查詢紅樓夢這本書出版社的名字
    # select * from app01_book inner join app01_publish
    # on app01_book.publish_id=app01_publish.nid
    ret=Book.objects.filter(name='紅樓夢').values('publish__name')
    print(ret)
    ret=Publish.objects.filter(book__name='紅樓夢').values('name')
    print(ret)
    # sql 語句就是from的表不同
    # -------多對多正向查詢
    # 查詢紅樓夢全部的做者
    ret=Book.objects.filter(name='紅樓夢').values('authors__name')
    print(ret)
    # ---多對多反向查詢
    ret=Author.objects.filter(book__name='紅樓夢').values('name')
    ret=Author.objects.filter(book__name='紅樓夢').values('name','author_detail__addr')
    print(ret)

一對一查詢

# 查詢alex的手機號
    
    # 正向查詢
    ret=Author.objects.filter(name="alex").values("authordetail__telephone")

    # 反向查詢
    ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
# 查詢lqz的手機號
    # 正向查
    ret=Author.objects.filter(name='lqz').values('author_detail__telephone')
    print(ret)
    # 反向查
    ret= AuthorDatail.objects.filter(author__name='lqz').values('telephone')
    print(ret)

進階練習(連續跨表)

# 練習: 查詢人民出版社出版過的全部書籍的名字以及做者的姓名


    # 正向查詢
    queryResult=Book.objects.filter(publish__name="人民出版社")values_list("title","authors__name")
    # 反向查詢
    queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")


# 練習: 手機號以151開頭的做者出版過的全部書籍名稱以及出版社名稱


    # 方式1:
    queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151")
            .values_list("title","publish__name")
    # 方式2:    
    ret=Author.objects.filter(authordetail__telephone__startswith="151").values("book__title","book__publish__name")
# ----進階練習,連續跨表
    # 查詢手機號以33開頭的做者出版過的書籍名稱以及書籍出版社名稱
    # author_datail author book publish
    # 基於authorDatail表
    ret=AuthorDatail.objects.filter(telephone__startswith='33').values('author__book__name','author__book__publish__name')
    print(ret)
    # 基於Author表
    ret=Author.objects.filter(author_detail__telephone__startswith=33).values('book__name','book__publish__name')
    print(ret)
    # 基於Book表
    ret=Book.objects.filter(authors__author_detail__telephone__startswith='33').values('name','publish__name')
    print(ret)
    # 基於Publish表
    ret=Publish.objects.filter(book__authors__author_detail__telephone__startswith='33').values('book__name','name')
    print(ret)
publish = ForeignKey(Blog, related_name='bookList')
# 練習: 查詢人民出版社出版過的全部書籍的名字與價格(一對多)

# 反向查詢 再也不按表名:book,而是related_name:bookList


    queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("bookList__title","bookList__price")

反向查詢時,若是定義了related_name ,則用related_name替換表名,例如:

相關文章
相關標籤/搜索