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