django系列5.1--ORM对数据库的操作
Django--—ORM數(shù)據(jù)庫操作(圖書管理系統(tǒng)基本實(shí)例)
一.基本知識(shí)
MVC模式(Model–view–controller)是軟件工程中的一種軟件架構(gòu)模式,把軟件系統(tǒng)分為三個(gè)基本部分:模型(Model)、視圖(View)和控制器(Controller)。
ORM:對(duì)象關(guān)系映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換 。 從效果上說,它其實(shí)是創(chuàng)建了一個(gè)可在編程語言里使用的-–“虛擬對(duì)象數(shù)據(jù)庫”。
FBV (function base views)就是在視圖里使用函數(shù)處理請(qǐng)求。
CBV(class base views) 就是在視圖里使用類處理請(qǐng)求。
二.為項(xiàng)目添加新app
注意新添加app時(shí)應(yīng)在配置文件中的INSTALLED_APPS中寫入我們創(chuàng)建的app名稱
INSTALLED_APPS = ['django.contrib.admin', #這是django給你提供的一些特殊功能的配置(應(yīng)用,只是咱們看不到),也在應(yīng)用這里給配置的,這些功能如果你注銷了,那么我們執(zhí)行同步數(shù)據(jù)庫指令之后,就不會(huì)生成那些django自帶的表了。因?yàn)閳?zhí)行數(shù)據(jù)庫同步語句的時(shí)候,django會(huì)找這里面所有的應(yīng)用,找到他們的models來創(chuàng)建表'django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',"book" #直接寫app的名字也行,寫'app01.apps.App01Config'也行 ]三.創(chuàng)建與數(shù)據(jù)庫的連接
1.此時(shí)首先應(yīng)建立一個(gè)mysql數(shù)據(jù)庫,這里我創(chuàng)建的數(shù)據(jù)庫名為orm
2.settings.py文件中配置數(shù)據(jù)庫連接,(創(chuàng)建項(xiàng)目時(shí)有默認(rèn)的語句,找到DATABASES后修改補(bǔ)全即可)
# Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databasesDATABASES = {'default': {'ENGINE': 'django.db.backends.mysql', # 連接的數(shù)據(jù)庫類型'NAME': 'orm', # 數(shù)據(jù)庫名稱'USER':'root', # 用戶名'PASSWORD':'123','HOST':'127.0.0.1','PORT':3306# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # 創(chuàng)建項(xiàng)目時(shí)默認(rèn)用的數(shù)據(jù)庫類型} }sqlite數(shù)據(jù)庫下的db.sqlite3則是項(xiàng)目自動(dòng)創(chuàng)建 USER和PASSWORD分別是數(shù)據(jù)庫的用戶名和密碼。設(shè)置完后,再啟動(dòng)我們的Django項(xiàng)目前,我們需要激活我們的mysql。然后,啟動(dòng)項(xiàng)目,會(huì)報(bào)錯(cuò):no module named MySQLdb 。這是因?yàn)閐jango默認(rèn)你導(dǎo)入的驅(qū)動(dòng)是MySQLdb,可是MySQLdb 對(duì)于py3有很大問題,所以我們需要的驅(qū)動(dòng)是PyMySQL 所以,我們只需要找到項(xiàng)目名文件下的__init__.py,在里面寫入:
3.在項(xiàng)目app中的__init__.py 輸入下面代碼
import pymysqlpymysql.install_as_MySQLdb()4.創(chuàng)建數(shù)據(jù)庫表.先創(chuàng)建模式,項(xiàng)目目錄下的models.py
from django.db import models# Create your models here. class Book(models.Model):id = models.AutoField(primary_key=True)title = models.CharField(max_length=32)pub_date = models.DateField()price = models.DecimalField(max_digits=8,decimal_places=2)publish = models.CharField(max_length=20)def __str__(self): # 這里用來以后對(duì)數(shù)據(jù)庫操作時(shí)在控制臺(tái)輸出titile名稱return self.title5.需要在terminal中輸入兩行命令
python3 manage.py makemigrations # 創(chuàng)建腳本 python3 manage.py migrate # 遷移6.查看執(zhí)行的sql語句
在settings.py文件中加入
查看數(shù)據(jù)庫執(zhí)行代碼 LOGGING = {'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',},} }四.單表操作
在views.py中添加對(duì)數(shù)據(jù)庫的操作語句
#在邏輯代碼中導(dǎo)入你要操作的表 from app import modelsdef add_book(request):'''添加表記錄:param request: http請(qǐng)求信息:return:'''models.Book(title='人間失格',price=12,pub_date='2012-12-12',publish='文學(xué)出版社')1.添加表記錄
方式1:實(shí)例化對(duì)象就是一條表記錄
from app import modelsobj = models.Book(title='復(fù)活',price=12,pub_date='2012-12-12',publish='小出版社') obj.save()方式2:(我們一般使用方式二添加)
models.Book.objects.create(title='復(fù)活',price=12,pub_date='2012-12-12',publish='小出版社')2.查詢表記錄
查詢所有的記錄:
obj = models.Book.objects.all()使用values的結(jié)果:
obj = models.Book.objects.all().values() # <QuerySet [{'id': 1, 'title': '雪國列車2', 'pub_date': datetime.date(2012, 12, 1),常用的查詢API:
<1> all(): 查詢所有結(jié)果,結(jié)果是queryset類型<2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對(duì)象,結(jié)果也是queryset類型 Book.objects.filter(title='linux',price=100) #里面的多個(gè)條件用逗號(hào)分開,并且這幾個(gè)條件必須都成立,是and的關(guān)系,or關(guān)系的我們后面再學(xué),直接在這里寫是搞不定or的<3> get(**kwargs): 返回與所給篩選條件相匹配的對(duì)象,不是queryset類型,是行記錄對(duì)象,返回結(jié)果有且只有一個(gè),如果符合篩選條件的對(duì)象超過一個(gè)或者沒有都會(huì)拋出錯(cuò)誤。捕獲異常try。 Book.objects.get(id=1)<4> exclude(**kwargs): 排除的意思,它包含了與所給篩選條件不匹配的對(duì)象,沒有不等于的操作昂,用這個(gè)exclude,返回值是queryset類型 Book.objects.exclude(id=6),返回id不等于6的所有的對(duì)象,或者在queryset基礎(chǔ)上調(diào)用,Book.objects.all().exclude(id=6) <5> order_by(*field): queryset類型的數(shù)據(jù)來調(diào)用,對(duì)查詢結(jié)果排序,默認(rèn)是按照id來升序排列的,返回值還是queryset類型 models.Book.objects.all().order_by('price','id') #直接寫price,默認(rèn)是按照price升序排列,按照字段降序排列,就寫個(gè)負(fù)號(hào)就行了order_by('-price'),order_by('price','id')是多條件排序,按照price進(jìn)行升序,price相同的數(shù)據(jù),按照id進(jìn)行升序<6> reverse(): queryset類型的數(shù)據(jù)來調(diào)用,對(duì)查詢結(jié)果反向排序,返回值還是queryset類型<7> count(): queryset類型的數(shù)據(jù)來調(diào)用,返回?cái)?shù)據(jù)庫中匹配查詢(QuerySet)的對(duì)象數(shù)量。<8> first(): queryset類型的數(shù)據(jù)來調(diào)用,返回第一條記錄 Book.objects.all()[0] = Book.objects.all().first(),得到的都是model對(duì)象,不是queryset<9> last(): queryset類型的數(shù)據(jù)來調(diào)用,返回最后一條記錄<10> exists(): queryset類型的數(shù)據(jù)來調(diào)用,如果QuerySet包含數(shù)據(jù),就返回True,否則返回False. 空的queryset類型數(shù)據(jù)也有布爾值True和False,但是一般不用它來判斷數(shù)據(jù)庫里面是不是有數(shù)據(jù),如果有大量的數(shù)據(jù),你用它來判斷,那么就需要查詢出所有的數(shù)據(jù),效率太差了,用count或者exits例:all_books = models.Book.objects.all().exists() #翻譯成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通過limit 1,取一條來看看是不是有數(shù)據(jù)<11> values(*field): 用的比較多,queryset類型的數(shù)據(jù)來調(diào)用,返回一個(gè)ValueQuerySet——一個(gè)特殊的QuerySet,運(yùn)行后得到的并不是一系列.model的實(shí)例化對(duì)象,而是一個(gè)可迭代的字典序列,只要是返回的queryset類型,就可以繼續(xù)鏈?zhǔn)秸{(diào)用queryset類型的其他的查找方法,其他方法也是一樣的。<12> values_list(*field): 它與values()非常相似,它返回的是一個(gè)元組序列,values返回的是一個(gè)字典序列 <13> distinct(): values和values_list得到的queryset類型的數(shù)據(jù)來調(diào)用,從返回結(jié)果中剔除重復(fù)紀(jì)錄雙下劃線的單表查詢
Book.objects.filter(price__in=[100,200,300]) #price值等于這三個(gè)里面的任意一個(gè)的對(duì)象 Book.objects.filter(price__gt=100) #大于,大于等于是price__gte=100,別寫price>100,這種參數(shù)不支持 Book.objects.filter(price__lt=100) # 小于 同大于,不包含邊界值 Book.objects.filter(price__range=[100,200]) #sql的between and,大于等于100,小于等于200 Book.objects.filter(title__contains="python") #title值中包含python的 Book.objects.filter(title__icontains="python") #不區(qū)分大小寫 Book.objects.filter(title__startswith="py") #以什么開頭,istartswith 不區(qū)分大小寫 Book.objects.filter(pub_date__year=2012) # 日期查詢,年份為2012的數(shù)據(jù)關(guān)于value的用法
all_books = models.Book.objects.all().values('id','title') print(all_books) #<QuerySet [{'title': 'linux', 'id': 6}, {'title': '你好', 'id': 7}, {'title': 'linux', 'id': 8}, {'title': 'xxx', 'id': 9}, {'title': 'gogogo', 'id': 10}]>'''values做的事情:ret = [] #queryset類型for obj in Book.objects.all():temp = { #元素是字典類型'id':obj.id,'title':obj.title}ret.append(temp)'''關(guān)于時(shí)間問題:日期查詢
all_books = models.Book.objects.filter(pub_date__year=2012) # 找2012年的所有書籍 all_books = models.Book.objects.filter(pub_date__year__gt=2012) # 找大于2012年的所有書籍 all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2) # 找2019年月份的所有書籍,如果明明有結(jié)果,你卻查不出結(jié)果,是因?yàn)閙ysql數(shù)據(jù)庫的時(shí)區(qū)和咱們django的時(shí)區(qū)不同導(dǎo)致的,了解一下就行了,你需要做的就是將django中的settings配置文件里面的USE_TZ = True改為False,就可以查到結(jié)果了,以后這個(gè)值就改為False,而且就是因?yàn)樵蹅冇玫膍ysql數(shù)據(jù)庫才會(huì)有這個(gè)問題,其他數(shù)據(jù)庫沒有這個(gè)問題。當(dāng)查詢?nèi)掌诔霈F(xiàn)問題時(shí):
將settings.py中最下面的USE_TZ = False改為True
USE_TZ = True不是跨時(shí)區(qū)的應(yīng)用,不需要考慮時(shí)區(qū)問題,就將這個(gè)值改為False,mysql是對(duì)時(shí)區(qū)不敏感,django往mysql里面出數(shù)據(jù)的時(shí)候,如果這里的值為True,那么將讓mysql強(qiáng)制使用UTC時(shí)間,那么我們存儲(chǔ)進(jìn)入的時(shí)間,當(dāng)你查詢的時(shí)候,你就會(huì)發(fā)現(xiàn),時(shí)間晚了8小時(shí),也就是說你存時(shí)間的時(shí)候被改為了UTC時(shí)間,本地是東八區(qū),比UTC時(shí)間多8小時(shí)
3.修改表記錄
update只能是QuerySet類型才能調(diào)用,model對(duì)象不能直接調(diào)用更新方法,所以使用get方法獲取對(duì)象的時(shí)候是不能使用update方法的
Book.objects.filter(title__startswith="復(fù)活").update(price=12)注意:
<input type="date" class="form-control" id="book_pub_date" placeholder="出版日期" name="book_pub_date" value="{{ edit_obj.pub_date|date:'Y-m-d' }}">type='date'的input標(biāo)簽,value的值必須是'Y-m-d'的格式,這個(gè)標(biāo)簽才能認(rèn)識(shí)并被賦值,所以,要通過date過濾給它改變格式。
4.刪除表記錄
刪除方法.delete()的調(diào)用者可以是一個(gè)model對(duì)象,也可以是一個(gè)queryset集合.它運(yùn)行時(shí)立即刪除對(duì)象而不返回任何值,也可以一次刪除多個(gè)對(duì)象.每個(gè)queryset都有一個(gè)delete()方法
models.Book.objects.filter(title='復(fù)活').delete() # 刪除標(biāo)題為復(fù)活的Book對(duì)象任何情況下,QuerySet中的delete()方法都只使用一條SQL語句一次性刪除所有對(duì)象,而并不是分別刪除誒個(gè)對(duì)象,如果想使用model中自定義的delete()方法,就要自行調(diào)用每個(gè)對(duì)象的delete()方法(例如,遍歷 QuerySet,在每個(gè)對(duì)象上調(diào)用 delete()方法),而不是使用 QuerySet 中的 delete()方法。
在Django刪除對(duì)象時(shí),會(huì)模仿SQL約束 ON DELETE CASCDE的行為(刪除一個(gè)對(duì)象時(shí)也會(huì)刪除與它相關(guān)聯(lián)的外鍵對(duì)象)
b = Blog.objects.get(pk=1) # This will delete the Blog and all of its Entry objects. b.delete()delete() 方法是 QuerySet 上的方法,但并不適用于 Manager 本身。這是一種保護(hù)機(jī)制,是為了避免意外地調(diào)用 Entry.objects.delete() 方法導(dǎo)致 所有的 記錄被誤刪除。如果你確認(rèn)要?jiǎng)h除所有的對(duì)象,那么你必須顯式地調(diào)用:
Entry.objects.all().delete()轉(zhuǎn)載于:https://www.cnblogs.com/robertx/p/10447094.html
總結(jié)
以上是生活随笔為你收集整理的django系列5.1--ORM对数据库的操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis主线流程源码解析
- 下一篇: C++初步学习