1. 程式人生 > >ORM增刪改查

ORM增刪改查

目錄

  • orm
    • django 連線mysql順序
      • 1 settings配置檔案中
      • 2 專案資料夾下的init檔案中寫上下面內容,
      • 補充
      • 3 models檔案中建立一個類(類名就是表名)
      • 4.執行資料庫同步指令,
      • 5 建立記錄
      • 6.欄位約束
    • 資料庫的操作(django)
      • 增:
      • 時間問題
      • 批量插入(bulk_create)
      • form表單提交之字典
      • 查詢api
      • filter雙下劃線查詢
    • 多表查詢
      • 表結構
      • 注意事項
      • 多對多關係
      • 一對一關係
      • 多對一
      • 外來鍵
    • admin使用超級管理員
      • 1.連線資料庫
      • 2.建立超級管理員
      • 增刪改查
      • 增加
      • 刪除
      • 基於物件的跨表查詢
      • 一對一
      • 一對多
      • 多對多

orm

1.MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫,這極大的減輕了開發人員的工作量

2.ORM是“物件-關係-對映”的簡稱。

3.執行流程

​ 類物件--->sql--->pymysql--->mysql服務端--->磁碟

​ orm其實就是將類物件的語法翻譯成sql語句的一個引擎

​ orm語句 -- sql -- 呼叫pymysql客戶端傳送sql -- mysql服務端接收到指令並執行

django 連線mysql順序

1 settings配置檔案中

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',   # 引擎
        'NAME': 'day53',            # 資料庫名稱
        'HOST': '127.0.0.1',        # IP
        'PORT': 3306,               # 埠號
        'USER': 'root',         # 使用者名稱
        'PASSWORD': '123'           # 密碼
    }
}

2 專案資料夾下的init檔案中寫上下面內容,

​ 作用:用pymysql替換mysqldb(djnago自帶的)

mysqldb 不能python3.4以上的版本

需要使用第三方模組pymysql進行替換

app01中的--init--檔案

補充

MySQLdb的是一個介面連線到MySQL資料庫伺服器從Python
MySQLdb並不支援Python3.4之後版本
原因:
#python預設連線的MySQLdb並不支援Python3.4之後版本
解決辦法:
#12使用第三方模組pymysql進行替換
import pymysql
pymysql.install_as_MySQLdb()

3 models檔案中建立一個類(類名就是表名)

#引用一個模組 from django.db import models
class UserInfo(models.Model):
     id = models.AutoField(primary_key=True)
     name = models.CharField(max_length=10)
     bday = models.DateField()
     checked = models.BooleanField()
# 1  翻譯成sql語句
# 2  django內建的一個sqlite客戶端將sql語句發給sqlite服務端
# 3  服務端拿到sql,到磁盤裡面進行了資料操作(create table app01_userinfo(id name...))

4.執行資料庫同步指令,

新增欄位的時候別忘了,該欄位不能為空,所有要麼給預設值,要麼設定它允許為空 null=True

 #注意在每次增加欄位時候都需要執行一遍這個方法
 python manage.py makemigrations#建立一個表記錄
python版本號
 python manage.py migrate 執行記錄

資料庫問題mysql 更改時區和改變版本號mysql for 5.1

5 建立記錄

(例項一個物件,呼叫save方法)

models.py

#建立一條記錄,增
def query(request): 
    new_obj = models.UserInfo(
        id=2,
        name='子文',
        bday='2019-09-27',
        checked=1,

    )
    new_obj.save()  
    #翻譯成sql語句,
    #然後呼叫pymysql,傳送給服務端 
    相當於執行insert into app01_userinfo values(2,'子文','2019-09-27',1)

    return HttpResponse('xxx')

6.欄位約束

通過選項實現對欄位的約束,選項如下:

null:如果為True,表示允許為空,預設值是False。
blank:如果為True,則該欄位允許為空白,預設值是False。
對比:null是資料庫範疇的概念,blank是表單驗證證範疇的。
db_column:欄位的名稱,如果未指定,則使用屬性的名稱。
db_index:若值為True, 則在表中會為此欄位建立索引,預設值是False。
default:預設值。
primary_key:若為True,則該欄位會成為模型的主鍵欄位,預設值是False,一般作為AutoField的選項使用。
unique:如果為True, 這個欄位在表中必須有唯一值,預設值是False。

配置資料庫

python3 manage.py makemigrations   建立指令碼
python3 manage.py migrate   遷移

建立app01中的--init--檔案

class Book(models.Model):  #必須要繼承的
    nid = models.AutoField(primary_key=True)  #自增id(可以不寫,預設會有自增id AutoField是自增)
    title = models.CharField(max_length=32)
    publishDdata = models.DateField()  #出版日期
    author = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5,decimal_places=2)  #一共5位,保留兩位小數

替換資料庫的時候需要重新建立表記錄

更改欄位時候也需要

python36 manage.py makemigrations   建立指令碼
python36 manage.py migrate  遷移

資料庫的操作(django)

建立欄位django特殊說明

1.欄位的值預設是不為空的 需要手動設定 不然會報錯

2.主鍵無需手動新增 自動生成id欄位(主鍵)
3.引用模組from django.db import models

獲取id欄位的兩種方式

1.表名.id
例
book.id
2.表名.pk
例
book.pk

增:

方式1:
    new_obj = models.UserInfo(#直接表名建立
        過程
        #1.先例項化產生物件,2.然後呼叫save方法儲存
        id=2,
        name='子文',
        bday='2019-09-27',
        checked=1,

    )
    new_obj.save() 
方式2:
    # ret 是建立的新的記錄的model物件(重點)
    ret = models.UserInfo.objects.create(
        name='衛賀',
        bday='2019-08-07',
        checked=0
    )

    print(ret)  #UserInfo object  
    print(ret.name)  #UserInfo object 
    print(ret.bday)  #UserInfo object

時間問題

models.UserInfo.objects.create(
        name='楊澤濤2',
        bday=current_date,
        # now=current_date,  直接插入時間沒有時區問題
        checked=0
    )
    但是如果讓這個欄位自動來插入時間,就會有時區的問題,auto_now_add建立記錄時自動添加當前建立記錄時的時間,存在時區問題
now = models.DateTimeField(auto_now_add=True,null=True)
解決方法:
    settings配置檔案中將USE_TZ的值改為False
    # USE_TZ = True
    USE_TZ = False  # 告訴mysql儲存時間時按照當地時間來寸,不要用utc時間
使用pycharm的資料庫客戶端的時候,時區問題要注意

from django.db import models
簡單查詢:filter()  -- 結果是queryset型別的資料裡面是一個個的model物件,類似於列表
    models.UserInfo.objects.filter(id=7).delete()  #queryset物件呼叫
    models.UserInfo.objects.filter(id=7)[0].delete()  #model物件呼叫

方式1:update
    # models.UserInfo.objects.filter(id=2).update(
    #     name='籃子文',
    #     checked = 0,
    #
    # )
    # 錯誤示例,model物件不能呼叫update方法
    # models.UserInfo.objects.filter(id=2)[0].update(
    #     name='加籃子+2',
    #     # checked = 0,
    # )
方式2 
    ret = models.UserInfo.objects.filter(id=2)[0]
    ret.name = '加籃子+2'
    ret.checked = 1
    ret.save()
    

更新時的auto_now引數
    # 更新記錄時,自動更新時間,建立新紀錄時也會幫你自動新增建立時的時間,但是在更新時只有使用save方法的方式2的形式更新才能自動更新時間,有缺陷,放棄
    now2 = models.DateTimeField(auto_now=True,null=True)

批量插入(bulk_create)

步驟
1.把查詢的物件放入字典裡一次性傳入前端進行互動    
    # bulk_create
    obj_list = []
    for i in range(20):
        obj = models.Book(
            title=f'金瓶{i}',
            price=20+i,
            publish_date=f'2019-09-{i+1}',
            publish='24期出版社'
        )
        obj_list.append(obj)

    models.Book.objects.bulk_create(obj_list)  #批量建立

form表單提交之字典

request.POST --  querydict型別 {'title': ['asdf '], 'price': ['212'], 'publish_date': ['2019-09-12'], 'publish': ['asdf ']}
data = request.POST.dict() -- 能夠將querydict轉換為普通的python字典格式

建立資料
    models.Book.objects.create(
            ## title=title,  #title='asdf '
            ## price=price,  #price='212'
        ## publish_date=publish_date,
        #'publish_date': ['2019-09-12']
            ## publish=publish,
        #publish=['asdf ']
            **data#通過打散把鍵和值轉換成以上資料
        )

查詢api

篩選基本都是queryset型別

reservse 必須要排序才能反轉

1.all()

查詢對應表名的所有物件,結果是物件列表

結果為queryset型別

寫法
models.表名.object.all()
例如
all_books = models.Book.objects.all()
數量過多會自動截斷

2.filter條件查詢

過濾出符合條件的資料

filter 條件查詢
    ret = models.Book.objects.filter(title='金瓶7',publish='24期出版社') #相當於mysql資料庫中and多條件查詢
    查詢條件不能匹配到資料時,不會報錯,返回一個空的queryset,<QuerySet []>,如果沒有寫查詢條件會獲取所有資料,queryset型別的資料還能夠繼續呼叫fitler方法

3.get()

得到一個滿足條件的model物件 有且只有一個

ret = models.Book.objects.get() #得到的是一個model物件,有且只能有一個
    1. 查不到資料會報錯 :Book matching query does not exist.
    2. 超過一個就報錯 :returned more than one Book -- it returned 13!

4.exclude()#排除

#除了這個之外
models.BOOK.objects.exclude(title__startswith=('金瓶'))
#model型別不能使用這個方法
1.object能夠呼叫,models.Book.objects.exclude(title__startswith='金瓶')    
2.queryset型別資料能夠呼叫,     models.Book.objects.all().exclude(title__startswith='金瓶')

5.order by()排序

models.Book.objects.all().order_by('-price','id')  
#sql語句寫法 orderby price desc,id asc;
models型別不能使用
排序order by 加上-欄位名 不加是升序

6.reverse() 反轉

models.Book.objects.all().order_by('id').reverse()  #資料排序之後才能反轉

7.count()

計數,統計返回結果的數量

models.Book.objects.all().count() 
sql語句 聚合函式

8.first()

類似於models.類名(表名).objects.filter(條件判斷)[0]
models.類名(表名).objects.filter(條件判斷).first()
#返回滿足條件的第一條資料

返回第一條資料,結果是model物件型別

9.last()

返回最後一條資料,結果是model物件型別

ret = models.Book.objects.all().first()
ret = models.Book.objects.all().last()

10.exists()

判斷返回結果集是不是有資料

models.Book.objects.filter(id=9999).exists() 
#有結果就是True,沒有結果就是False

11.values

(返回的queryset型別,裡面是字典型別資料)

12.values_list

(返回的queryset型別,裡面是陣列型別資料)

ret = models.Book.objects.filter(id=9).values('title','price') 
ret = models.Book.objects.all().values_list('title','price')
ret = models.Book.objects.all().values()
ret = models.Book.objects.values()  #呼叫values或者values_list的是objects控制器,那麼返回所有資料 

13.distinct()

去重,配置values和values_list來使用,不能帶有id 因為id預設唯一

models.Book.objects.all().values('publish').distinct()

filter雙下劃線查詢

queryset型別 篩選出來的是queryset型別

get篩選出來一個是model物件

queryset 型別的方法可以多次呼叫使用

13個api能呼叫的函式和方法(重點)

    # ret = models.Book.objects.all().values('publish').distinct()
    # ret = models.Book.objects.filter(price__gt=35)  #大於
    # ret = models.Book.objects.filter(price__gte=35) # 大於等於
    # ret = models.Book.objects.filter(price__lt=35) # 小於等於
    # ret = models.Book.objects.filter(price__lte=35) # 小於等於
    # ret = models.Book.objects.filter(price__range=[35,38]) # 大於等35,小於等於38   # where price between 35 and 38
    # ret = models.Book.objects.filter(title__contains='金瓶') # 欄位資料中包含這個字串的資料都要
    # ret = models.Book.objects.filter(title__contains='金瓶')
    # ret = models.Book.objects.filter(title__icontains="python")  # 不區分大小寫
    # from app01.models import Book
    # ret = models.Book.objects.filter(title__icontains="python")  # 不區分大小寫
    # ret = models.Book.objects.filter(title__startswith="py")  # 以什麼開頭,istartswith  不區分大小寫
    # ret = models.Book.objects.filter(publish_date='2019-09-15')

某年某月某日(對於日期的修改):
    ret = models.Book.objects.filter(publish_date__year='2018') 
    ret = models.Book.objects.filter(publish_date__year__gt='2018')#2018寫數字也可以
    ret = models.Book.objects.filter(publish_date__year='2019',publish_date__month='8',publish_date__day='1')
    
找欄位資料為空的雙下滑線
    models.Book.objects.filter(publish_date__isnull=True) #這個欄位值為空的那些資料

多表查詢

多表是會為減少資料的冗餘 加速查詢的效率

models.欄位型別()

表結構

rom django.db import models

# Create your models here.

class Author(models.Model):
    """
    作者表
    """
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    #一對一 authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)  #
    #一對一
    au=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE)

class AuthorDetail(models.Model):
    """
    作者詳細資訊表
    """
    birthday=models.DateField()
    telephone=models.CharField(max_length=11)
    addr=models.CharField(max_length=64)
    # class Meta:
        # db_table='authordetail' #指定表名
        # ordering = ['-id',]
class Publish(models.Model):
    """
    出版社表
    """
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)

class Book(models.Model):
    """
    書籍表
    """
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)
    #一對多
                                                                                                            publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
    多對多
    authors=models.ManyToManyField('Author',)

注意事項

#重中之重 不要把表名和庫名設定成一樣的
1.不寫欄位預設外來鍵預設連線id
2.創表預設建立主鍵 無需手動建立
3.oneto one 一對一#OneToOneField
4.id可以省略(自動連線另一個表的id欄位(主鍵))
5.djnago1.0版本可以不寫外來鍵 預設級聯刪除
6.djnago2.0版本必須寫on_delete=models.CASCADE
7.int型別不能進行模糊搜尋 例如 電話去模糊匹配 前三位
欄位名__startwith='151'
8.外來鍵欄位是賦值變數名=變數名_id
9.class AuthorDetail(models.Model) 建立表結構時 要繼承 models.Model方法
完整版寫法:
authorDetail=models.ForeignKey(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)  

class meta:

​   指定建立表時的源資訊

​   ordering 排序

db contrations 去除強制約束效果

多對多關係

# 多對多沒辦法使用一個表的外來鍵去設定
#多對多關係用第三張表儲存關係
優點
存入欄位資料少 資料庫小 增加執行效率
1.manytomany #authors=models.ManyToManyField('Author',)

ManyToManyField不會加欄位
book——author 一個表-另一個表
1.會生成一個表 欄位會自己建立
2。一個欄位是表名——id
3.下一個欄位是另一個表——id
會自動建立 對應id欄位,存入到一個屬性中
使用方法
4.類名或者例項化物件(表名)去呼叫這個屬性

一對一關係

#注意事項
1.如果兩張表資料不統一 是表資料少的去連線資料多的(資料多的是主表)
2.如果資料統一 建哪個東西
sql語句 把外來鍵變成unique(唯一)格式一樣
authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)  

多對一

1。對於外來鍵不需要唯一性, 
2。不建立外來鍵唯一(使用models.OneToOneField)建立外來鍵

外來鍵

1.完整版寫法
authorDetail=models.ForeignKey(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)  

2.id可以省略(自動連線另一個表的id欄位(主鍵))
publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
to=,to_field
#publishs是欄位名
2.連線表的兩種寫法
第一種寫法
to="加對應表名" 預設連線主鍵(id)
第二種寫法
publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
可以不寫 直接寫表名 但是如果載入在之後會報錯因為沒有預加載出來

admin使用超級管理員

1.連線資料庫

注意要先連線資料庫才能進入admin頁面輸入密碼進行操作

建立與資料庫之間的連線
1.在對應的app01 的models資料夾下建立好表,其中表包括(欄位型別(約束大小限制)
    1.2外來鍵的建立#需要注意的是1.1預設建立 2.0版本需要手動新增
        1.2.1 一對一建立外來鍵約束 #屬性名=OneToOneFlied(on_update=models.CASCADE)
                一對多建立外來鍵約束# 屬性名=foreignKey()
    也對就是對應的子程式的models
 2.建立表記錄
3.在對應子程式中把python預設支援的mysqldb 替換成pymysql
原因mysqldb不支援3.4以上版本

2.建立超級管理員

寫法 createsuperuser
兩種寫法
1.pycharm的一個控制檯 
#1.manage.py@dbcont > createsuperuser#一開始顯示這個 
使用createsuperuser建立管理員

2.python控制檯
2.1python36 manage.py createsuperuser#建立超級管理員
2.2同理輸入賬號和密碼 郵箱可以不用輸入

建立資料(記錄)

1.把models的表匯入到admin
在對應app01(子程式中)的admin.py檔案中
2.from django.contrib import admin
from app01 import models
admin.site.register(models.author)#格式 admin.site.reister(models.類名(表名))

增刪改查

在對應子程式的view視圖裡寫增刪改查

注意要先引用models模組(對應的models.py檔案)

增加

一對一

# 一對一
    # au_obj = models.AuthorDetail.objects.get(id=4)
    查詢出對應的models物件 存入表類中


    models.Author.objects.create(
        name='海狗',
        age=59,
        # 兩種方式
        au_id=4
        # au=au_obj
        #屬性對應的值是對應的models物件
    )

一對多

與一對一的區別

對於連線欄位沒有唯一的約束

     pub_obj = models.Publish.objects.get(id=3)
    
     models.Book.objects.create(
         title='xx2',
         price=13,
         publishDate='2011-11-12',
         publishs=pub_obj, 
         #類屬性作為關鍵字時,值為model物件
         publishs_id=3  
         # 如果關鍵字為資料庫欄位名稱,那麼值為關聯資料的值
     )

多對多

多對多關係表記錄的增加

 ziwen = models.Author.objects.get(id=3)
 haigou = models.Author.objects.get(id=5)

new_obj = models.Book.objects.create(
    title='海狗產後護理第二部',
    price=0.5,
    publishDate='2019-09-29',
    publishs_id=2,
)
new_obj是一個物件 
#第一種寫法
new_obj.authors.add(對應外來鍵欄位的值)#物件.屬性.方法名新增add
new_obj.authors.add(3,5) #*args  **kwargs
#新增的多個值用逗號隔開
new_obj.authors.add(*[3,5])  # 用的最多,
用法:
1.select 下拉框 的值是一個列表 使用name屬性 檢視對應value的值
2.多選的value值 是提交到後端是一個列表
3.使用*[value]打散#*[3,5]

#第二種寫法 新增model物件
new_obj.authors.add(ziwen, haigou)
建立完欄位之後要把對應的關係欄位寫到第三張表裡

刪除

一對一

models.AuthorDetail.objects.filter(id=3).delete()
models.Author.objects.filter(id=3).delete()

一對多

預設級聯刪除

關聯的表是主表 主表刪除子表的相對應的整條欄位也被刪除

models.Publish.objects.filter(id=3).delete()#Publish是主表
models.book.objects.filter(id=3).delete()

多對多

只操作對應第三張表
    book_obj = models.Book.objects.get(id=2)
    book_obj.authors.add()  # 新增
    book_obj.authors.remove(1)  #刪除括號裡對應的外來鍵關聯的id
    book_obj.authors.clear()  # 清除,篩選出的所有的對應外來鍵關係欄位
    book_obj.authors.set(['1','5'])  # 先清除對應外來鍵關係欄位再新增,相當於修改
    #易錯點
    不是在原位置修改是刪除這條對應記錄,再去新增新紀錄

    # 改
    ret = models.Publish.objects.get(id=2)
    models.Book.objects.filter(id=5).update(
         title='華麗麗',
         #publishs=ret,
         publishs_id=1,
     )
    兩種方式
    publishs=ret#使用屬性 對應的值是model物件
    publishs_id=1#對應的id值

基於物件的跨表查詢

obj=models.Author.objects.get(name='王洋')和filter用法一樣出來的型別不一樣
obj=models.Author.objects.filter(name='王洋').first()

get和filter的區別

    1.filter篩選出來的是queryset物件需要轉成model物件
    1.2如果是多個值 需要for迴圈取值轉換
    寫法
   a=models.Author.objects.filter()[0]
    a查詢出來多個值 這樣使用就只能查出一個
    需要for 迴圈取值
    2.get是對應的model物件 可以直接拿來用

反向查詢和正向查詢的區別

1.正向查詢是建立外來鍵關係的屬性 在當前表中
    用法
        obj=models.Author.objects.get(name='王洋')
        obj.對應的外來鍵屬性名.欄位名

2.反向查詢是表中沒有對應建立外來鍵關係的屬性
    用法·
        obj=models.Author.objects.get(name='王洋')
        obj.小寫表名.欄位名 #obj,表名找到對應表
    如果 查詢東西多 
    1.需要用   注意:正向查和反向查有一些區別,當正相查結果為多個時,直接obj.對應的外來鍵屬性名.all()既可以,但是反向查有一些不同obj.小寫表名_set.all()屬性名(欄位)_set.all() 
    取值
    2.使用 for迴圈列表進行物件取值
    舉例
    obj=models.表名.objects.filter(name='子文')
    ret=obj.book_set.all()#查詢出來的是個列表s
    for i in ret:
        print(i.title)
#注意:正向查和反向查有一些區別,當正相查結果為多個時,直接obj.對應的外來鍵屬性名.all()既可以,但是反向查有一些不同obj.小寫表名_set.all()

一對一

# 一對一
     正向查詢  物件.屬性
     obj = models.Author.objects.filter(name='王洋').first()
     ph = obj.au.telephone
     print(ph)

    # 查一下電話號碼為120的作者姓名
    # 反向查詢  物件.小寫的表名
     obj = models.AuthorDetail.objects.filter(telephone=120).first()
     ret = obj.author.name  #陳碩
     print(ret)

一對多

  
  
    # 查詢
    # 一對多
    # 查詢一下 海狗的慫逼人生這本書是哪個出版社出版的  正向查詢
     obj = models.Book.objects.filter(title='海狗的慫逼人生').first()
     ret = obj.publishs.name
     print(ret)  #24期出版社
    #  查詢一下 24期出版社出版過哪些書
     obj = models.Publish.objects.filter(name='24期出版社').first()
    
     ret = obj.book_set.all() #<QuerySet [<Book: 母豬的產後護理>, <Book: 海狗的慫逼人生>]>
     for i in ret:
         print(i.title)

    

多對多

關於多對多正向反向查詢的的解釋

一句話概括
    是兩個的表的關係屬性在哪個表裡(類) 不是外來鍵欄位存在哪個表
解釋
    1.多對多需要建立在資料之上 因為沒有資料的支援沒辦法建立外來鍵,建立外來鍵約束
    2.多對多采用把關係存在第三張表裡
    3.基於物件的查詢是根據屬性查詢 
    4.兩個表的關係屬性在哪個表裡 哪個表就是正向查詢

具體事例

# 多對多
如果post請求多個值使用getlist(欄位)
寫法
obj=request.POST.getlist("author_id")
#取得的是一個列表
    # 海狗的慫逼人生 是哪些作者寫的 -- 正向查詢
     obj = models.Book.objects.filter(title='海狗的慫逼人生').first()
     ret = obj.authors.all()#可以直接查詢到作者對應的名字 (直接查詢到)
    
     print(ret)  #<QuerySet [<Author: 王洋>, <Author: 海狗>]>
     for i in ret:
         print(i.name)

    # 查詢一下海狗寫了哪些書 -- 反向查詢
     obj = models.Author.objects.filter(name='海狗').first()
     ret = obj.book_set.all()
     print(ret)
     for i in ret:
         print(i.publishs.name)
         print(i.title)
     return HttpResponse('ok')