一、Django連接數(shù)據(jù)庫(kù)操作
1、創(chuàng)建數(shù)據(jù)庫(kù) (注意設(shè)置 數(shù)據(jù)的字符編碼)
由于Django自帶的orm是data_first類型的ORM,使用前必須先創(chuàng)建數(shù)據(jù)庫(kù)
create database ayalysis default character set utf8 collate utf8_general_ci;
2、修改project中的settings.py文件中設(shè)置 連接 MySQL數(shù)據(jù)庫(kù)(Django默認(rèn)使用的是sqllite數(shù)據(jù)庫(kù))
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'ayalysis',
'USER': 'totd',
'PASSWORD': 'totd890',
'HOST': '192.168.182.128',
'PORT': '3306',
}
}
3、查看orm操作執(zhí)行的原生SQL語(yǔ)句,在project中的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',
},
}
}
4、修改project 中的__init__py 文件設(shè)置 Django默認(rèn)連接MySQL的方式
import pymysql
pymysql.install_as_MySQLdb()
5、setings文件注冊(cè)APP
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
]
6、進(jìn)行數(shù)據(jù)遷移,在winds cmd或者Linux shell的項(xiàng)目的manage.py目錄下執(zhí)行
python manage.py makemigrations #根據(jù)app下的migrations目錄中的記錄,檢測(cè)當(dāng)前model層代碼是否發(fā)生變化?
python manage.py migrate #把orm代碼轉(zhuǎn)換成sql語(yǔ)句去數(shù)據(jù)庫(kù)執(zhí)行
python manage.py migrate --fake #只記錄變化,不提交數(shù)據(jù)庫(kù)操作
二、字段類型
Django提供了很多字段類型,比如URL/Email/IP/ 但是mysql數(shù)據(jù)沒(méi)有這些類型,這類型存儲(chǔ)到數(shù)據(jù)庫(kù)上本質(zhì)是字符串?dāng)?shù)據(jù)類型,其主要目的是為了封裝底層SQL語(yǔ)句
1. 字符串類
name=models.CharField(max_length=32)
- EmailField(CharField):
- IPAddressField(Field)
- URLField(CharField)
- SlugField(CharField)
- UUIDField(Field)
- FilePathField(Field)
- FileField(Field)
- ImageField(FileField)
- CommaSeparatedIntegerField(CharField)
models.CharField 對(duì)應(yīng)的是MySQL的varchar數(shù)據(jù)類型
MySQL知識(shí)點(diǎn)補(bǔ)充:
char 和 varchar的區(qū)別 :
共同點(diǎn)是存儲(chǔ)數(shù)據(jù)的長(zhǎng)度,不能 超過(guò)max_length限制;
不同點(diǎn)是varchar能根據(jù)數(shù)據(jù)實(shí)際長(zhǎng)度存儲(chǔ),char按指定的max_length來(lái)存儲(chǔ)數(shù)據(jù);所有前者更節(jié)省硬盤空間。
2. 時(shí)間字段(詳細(xì)使用)
- models.DateTimeField(null=True)
- models.DateField()
- models.TimeField() # 不常用
3、數(shù)字字段
(max_digits=30,decimal_places=10)總長(zhǎng)度30小數(shù)位 10位)
- models.IntegerField() # 數(shù)字
- models.FloatField() # 浮點(diǎn)
- models.DecimalField(max_digits=8,decimal_places=3) # 精確浮點(diǎn)
4、枚舉字段
choice=(
(1, '男'),
(2, '女'),
(3, '其他')
)
gender=models.IntegerField(choices=choice) # 枚舉類型
擴(kuò)展:在數(shù)據(jù)庫(kù)存儲(chǔ)枚舉類型,比外鍵有什么優(yōu)勢(shì)?
1、無(wú)需連表查詢性能低,省硬盤空間(選項(xiàng)不固定時(shí)用外鍵)
2、在modle文件里不能動(dòng)態(tài)增加(選項(xiàng)一成不變用Django的choice)
5、其他字段
db_index = True 表示設(shè)置索引
unique(唯一的意思) = True 設(shè)置唯一索引
聯(lián)合唯一索引
class Meta:
unique_together = (
('email','ctime'),
)
聯(lián)合索引(不做限制)
index_together = (
('email','ctime'),
)
ManyToManyField(RelatedField) #多對(duì)多操作
三、字段參數(shù)介紹
- 數(shù)據(jù)庫(kù)級(jí)別生效
- Django admin級(jí)別生效
針對(duì) dango_admin生效的參數(shù)(正則匹配)(使用Django admin就需要關(guān)心以下參數(shù)?。。?/li>
- blank #是否為空
- editable=False # 是否允許編輯
- help_text="提示信息" # 提示信息
- choices=choice # 提供下拉框
- error_messages="錯(cuò)誤信息" # 錯(cuò)誤信息
- validators # 自定義錯(cuò)誤驗(yàn)證(列表類型),從而定制想要的驗(yàn)證規(guī)則(EmailValidator,URLValidator,DecimalValidator,MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator)
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator
test = models.CharField(
max_length=32,
error_messages={
'c1': '優(yōu)先錯(cuò)信息1',
'c2': '優(yōu)先錯(cuò)信息2',
'c3': '優(yōu)先錯(cuò)信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='錯(cuò)誤了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又錯(cuò)誤了', code='c2'),
EmailValidator(message='又錯(cuò)誤了', code='c3'), ]
四、單表操作
1. ORM使用方式
ORM操作可以使用類實(shí)例化,obj.save()的方式,也可以使用create()的形式
2. QuerySet數(shù)據(jù)類型介紹
- QuerySet與惰性機(jī)制:
所謂惰性機(jī)制指Userinfo.objects.all()或者.filter()等都只是返回了一個(gè)QuerySet(查詢結(jié)果集對(duì)象),它并不會(huì)馬上執(zhí)行sql,而是當(dāng)調(diào)用QuerySet的時(shí)候才執(zhí)行。 - QuerySet特點(diǎn):
<1>可迭代的
<2>可切片
<3>惰性計(jì)算和緩存機(jī)制
def queryset(request):
books=models.Book.objects.all()[:10] #切片 應(yīng)用分頁(yè)
books = models.Book.objects.all()[::2]
book= models.Book.objects.all()[6] #索引
print(book.title)
for obj in books: #可迭代
print(obj.title)
books=models.Book.objects.all() #惰性計(jì)算--->等于一個(gè)生成器,不應(yīng)用books不會(huì)執(zhí)行任何SQL操作
# query_set緩存機(jī)制1次數(shù)據(jù)庫(kù)查詢結(jié)果query_set都會(huì)對(duì)應(yīng)一塊緩存,再次使用該query_set時(shí),不會(huì)發(fā)生新的SQL操作;
#這樣減小了頻繁操作數(shù)據(jù)庫(kù)給數(shù)據(jù)庫(kù)帶來(lái)的壓力;
authors=models.Author.objects.all()
for author in authors:
print(author.name)
print('-------------------------------------')
models.Author.objects.filter(id=1).update(name='張某')
for author in authors:
print(author.name)
#但是有時(shí)候取出來(lái)的數(shù)據(jù)量太大會(huì)撐爆緩存,可以使用迭代器優(yōu)雅得解決這個(gè)問(wèn)題;
models.Publish.objects.all().iterator()
return HttpResponse('OK')
3. 增刪改查操作
- 增
orm添加一條記錄的方法
def orm(request):
# 單表
# 1、表.objects.create()
models.Publish.objects.create(name='浙江出版社',addr="浙江.杭州")
models.Classify.objects.create(category='武俠')
models.Author.objects.create(name='金庸',sex='男',age=89,university='東吳大學(xué)')
# 2、類實(shí)例化:obj=類(屬性=XX) obj.save()
obj=models.Author(name='吳承恩',age=518,sex='男',university='龍溪學(xué)院')
obj.save()
# 1對(duì)多
# 1、表.objects.create()
models.Book.objects.create(title='笑傲江湖',price=200,date=1968,classify_id=6, publish_id=6)
# 2、類實(shí)例化:obj=類(屬性=X,外鍵=obj)obj.save()
classify_obj=models.Classify.objects.get(category='武俠')
publish_obj=models.Publish.objects.get(name='河北出版社')
# 注意以上獲取得是和 book對(duì)象 向關(guān)聯(lián)的(外鍵)的對(duì)象
book_obj=models.Book(title='西游記',price=234,date=1556,classify=classify_obj,publish=publish_obj)
book_obj.save()
# 多對(duì)多
# 如果兩表之間存在雙向1對(duì)N關(guān)系,就無(wú)法使用外鍵來(lái)描述其關(guān)系了;只能使用多對(duì)多的方式,新增第三張表關(guān)系描述表;
book=models.Book.objects.get(title='笑傲江湖')
author1=models.Author.objects.get(name='金庸')
author2=models.Author.objects.get(name='張根')
book.author.add(author1,author2)
# 書籍和作者是多對(duì)多關(guān)系,
# 切記:如果兩表之間存在多對(duì)多關(guān)系,例如書籍相關(guān)的所有作者對(duì)象集合,作者也關(guān)聯(lián)的所有書籍對(duì)象集合
book=models.Book.objects.get(title='西游記')
author=models.Author.objects.get(name='吳承恩')
author2 = models.Author.objects.get(name='張根')
book.author.add(author,author2)
# add() # 添加
# clear() # 清空
# remove() # 刪除某個(gè)對(duì)象
return HttpResponse('OK')
根據(jù)條件判斷,增加?更新?
# 根據(jù)user=user去查找,如果找到更新 如果沒(méi)有找到創(chuàng)建defaults={} 中的數(shù)據(jù)
tk = gen_tcoken(username)
models.Token.objects.update_or_create(user=user, defaults={'token': tk})
- 刪
# 刪除指定條件的數(shù)據(jù)
models.Tb1.objects.filter(name='seven').delete()
- 改
def delete(request):
# 修改方式1 update()
ret = models.Book.objects.filter(id=1).update(price=3)
# 修改方式2 obj.save()
book_obj=models.Book.objects.get(id=1)
book_obj.price=5
book_obj.save()
- 查
def ormquery(request):
# query_set對(duì)象集合 [對(duì)象1、對(duì)象2、.... ]
books=models.Book.objects.all()
books=models.Book.objects.filter(id__gt=2,price__lt=100)
# 單個(gè)對(duì)象,沒(méi)有找到會(huì)報(bào)錯(cuò)
book=models.Book.objects.get(title__endswith='金')
book1 = models.Book.objects.filter(title__endswith='金').first()
book2 = models.Book.objects.filter(title__icontains='瓶').last()
# query_set字典集合 [{一條記錄},{一條記錄} ]
books=models.Book.objects.values(
'title','price',
'publish__name',
'date',
'classify__category', # 正向連表: 外鍵字段___對(duì)應(yīng)表字段
'author__name', # 反向連表: 小寫表名__對(duì)應(yīng)表字段
'author__sex', # 區(qū)別: 正向 外鍵字段__,反向 小寫表名__
'author__age',
'author__university')
books=models.Book.objects.values('title','publish__name').distinct()
# exclude 按條件排除。。。
# distinct()去重, exits()查看數(shù)據(jù)是否存在? 返回 true 和false
a=models.Book.objects.filter(title__icontains='金')
return HttpResponse('OK')
連表查詢
# 反向連表查詢:
# 1、通過(guò)object的形式反向連表, obj.小寫表名_set.all()
publish=models.Publish.objects.filter(name__contains='湖南').first()
books=publish.book_set.all()
for book in books:
print(book.title)
# 通過(guò)object的形式反向綁定外鍵關(guān)系
authorobj = models.Author.objects.filter(id=1).first()
objects = models.Book.objects.all()
authorobj.book_set.add(*objects)
authorobj.save()
# 2、通過(guò)values雙下滑線的形式,objs.values("小寫表名__字段")
# 注意對(duì)象集合調(diào)用values(),正向查詢是外鍵字段__XX,而反向是小寫表名__YY看起來(lái)比較容易混淆;
books=models.Publish.objects.filter(name__contains='湖南').values('name','book__title')
authors=models.Book.objects.filter(title__icontains='我的').values('author__name')
print(authors)
# fifter()也支持__小寫表名語(yǔ)法進(jìn)行連表查詢:在publish標(biāo)查詢 出版過(guò)《笑傲江湖》的出版社
publishs=models.Publish.objects.filter(book__title='笑傲江湖').values('name')
print(publishs)
# 查詢誰(shuí)(哪位作者)出版過(guò)的書價(jià)格大于200元
authors=models.Author.objects.filter(book__price__gt=200).values('name')
print(authors)
# 通過(guò)外鍵字段正向連表查詢,出版自保定的書籍;
city=models.Book.objects.filter(publish__addr__icontains='保定').values('title')
print(city)
五、ORM連表操作
在django使用orm的時(shí)候,我們可以把一對(duì)多,多對(duì)多,分為正向和反向查找兩種方式。
- 正向查找:
ForeignKey在 UserInfo表中,如果從UserInfo表開(kāi)始向其他的表進(jìn)行查詢,這個(gè)就是正向操作,反之如果從UserType表去查詢其他的表這個(gè)就是反向操作。
一對(duì)多:models.ForeignKey(其他表)
多對(duì)多:models.ManyToManyField(其他表)
一對(duì)一:models.OneToOneField(其他表) - 正向連表操作總結(jié):
所謂正、反向連表操作的認(rèn)定無(wú)非是Foreign_Key字段在哪張表決定的,F(xiàn)oreign_Key字段在哪張表就可以哪張表使用Foreign_Key字段連表,反之沒(méi)有Foreign_Key字段就使用與其關(guān)聯(lián)的 小寫表名;
1對(duì)多:對(duì)象.外鍵.關(guān)聯(lián)表字段,values(外鍵字段__關(guān)聯(lián)表字段)
多對(duì)多:外鍵字段.all()
- 反向連表操作總結(jié):
通過(guò)value、value_list、fifter 方式反向跨表:小寫表名__關(guān)聯(lián)表字段
通過(guò)對(duì)象的形式反向跨表:小寫表面_set().all()