Python的Django框架-資料庫查詢(增刪改查)
建立專案
django-admin startproject django_model
建立應用
python manage.py startapp model
- 配置應用 model, 編輯 django_model/settings.py 檔案:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages' ,
'django.contrib.staticfiles',
'model',
]
- 配置Mysql資料庫:編輯 django_model/settings.py 檔案, 內容如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # mysql資料庫引擎
'NAME': 'my_model', # 資料庫名字
'USER': 'root', # 使用者名稱
'PASSWORD': 'fe_cow', # 密碼
'HOST': 'localhost', # 主機
'PORT': '3306' # 埠
}
}
建立應用所需資料庫表, 首先我們建立資料庫:
create dababase my_model charset = utf8;
注意: 使用PyMysql資料庫驅動,需要在 djangomodel/_init__.py 中增加如下程式碼:(python2不需要配置這項)
import pymysql
pymysql.install_as_MySQLdb()
定義模型
- 定義模型其實就是定義一個python類;一個
模型類
資料庫中一張表
,一個模型類的例項
代表這個資料庫表中的一條特定的記錄
from django.db import models
class Publisher(models.Model):
"""出版社"""
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
country = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Author(models.Model):
"""作家"""
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
"""書"""
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author) # 書和作者是多對多的關係
publisher = models.ForeignKey(Publisher) # 書和出版者是多對一的關係
publication_date = models.DateField()
def __unicode__(self):
return self.title
定義完模型後,要執行資料庫遷移操作:
先執行
python manage.py makemigrations
在執行:python manage.py migrate
一張表中定義了多對多的關係,ORM會自動建立實現多對多關係的第三張表。
資料庫的操作
- 通過python shell 來演示資料庫的操作。在終端切換到專案根目錄下,輸入命令
python manage.py shell
進入shell操作環境。
增刪改查
1 建立記錄
方法一:例項化(呼叫save()方法
之前,Django不會訪問資料庫;save()方法
沒有返回值)
>>> from apps.models import Author
>>> author = Author(last_name='fe_cow')
>>> author.save()
>>> print author
fe_cow
方法二:create() (只用一條語句建立並儲存一個物件,使用create()方法
。)
>>> Author.objects.create(first_name='fe',last_name='cow', email='[email protected]')
方法三:get_or_create()
, 這種方法可以防止重複
(速度稍慢,因為會先查資料庫), 它返回一個元組。建立成功返回True,失敗的話False,不執行建立。
>>> author = Author.objects.get_or_create(last_name='fe_cow')
>>> print author
(<Author: fe_cow>, False) # False:說明已經重複 建立失敗
>>> author = Author.objects.get_or_create(last_name='cu_cow')
>>> print author
(<Author: cu_cow>, True) # True: 建立成功
2 查詢記錄
方法一:查詢所有物件 (all()方法
返回包含資料庫中所有物件的一個查詢集
。)
>>> author = Author.objects.all()
>>> print author
<QuerySet [<Author: fecow>, <Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
方法二:過濾查詢 (filter()
返回一個新的查詢集,它包含滿足查詢引數的物件。)
>>> author = Author.objects.filter(last_name='cu_cow')
>>> print author
<QuerySet [<Author: cu_cow>]>
方法三:指定查詢 (get
查詢只能返回一個物件
,多了少了都會引發DoesNotExist 異常)
>>> author = Author.objects.get(id=1)
>>> print author
fecow
方法四:雙下劃線查詢__
;__contains
:包含;__icontains
不區分大小寫;__regex
:正則查詢;__lt
:小於xxx;__lte
:小於等於xxx;__gt
:大於xxx;__gte
:大於等於xxx;__startswith()
: 以xxx開頭,;__istartswith()
:不區分大小寫以xxx開頭, __endswith()
:以xxx結尾;__iendswith()
:以xxx結尾不區分大小寫
- 以上使用方法基本上都一致:
物件
.objects.filter
(屬性
__xxx
) 例子如下:
>>> author = Author.objects.filter(id__gte=2)
>>> print author
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
- 單獨說一個特殊的
__in
判斷欄位在列表內。通常用pk指主鍵,不限於id,適用更好。
>>> author_list = Author.objects.values_list('id', flat=True)
# 返回的是:<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
>>> Author.objects.filter(pk__in=author)
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
方法五:first(), last()獲取查詢結果中單個物件
>>> Author.objects.filter(id__gte=2)
# 返回結果:QuerySet集合
<QuerySet [<Author: fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: cu_cow>]>
>>> Author.objects.filter(id__gte=2).first()
# 返回結果:objects物件 而且返回第一個物件
<Author: fe_cow>
>>> Author.objects.filter(id__gte=2).last()
<Author: cu_cow>
# 返回結果:objects物件 而且返回的是最後一個物件
方法六:通過values
查詢
values('欄位')
用字典形式,返回的是指定欄位的查詢結果;
>>> Author.objects.values('last_name')
<QuerySet [{'last_name': u'fecow'}, {'last_name': u'fe_cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cu_cow'}]>
# 返回字典列表;多個欄位間以逗號分隔
values_list('字典')
,返回的也是指定欄位的查詢結果
>>> Author.objects.values_list('last_name')
<QuerySet [(u'fecow',), (u'fe_cow',), (u'cow',), (u'cow',), (u'cow',), (u'cow',), (u'cu_cow',)]>
# 返回的是元組列表,多個欄位也是用逗號分割
values_list('欄位', flat=True)
flat=True :之後返回的是值列表
>>> Author.objects.values_list('id', flat=True)
<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
# 返回的是列表
方法六:exclude(**kwargs)
反向過濾
>>> Author.objects.exclude(id__gt=2)
<QuerySet [<Author: fecow>, <Author: fe_cow>]>
# 取反
方法七:exists()
>>> Author.objects.filter(id=2).exists()
True
# QuerySet包含資料返回True
>>> Author.objects.filter(last_name='Au_cow').exists()
False
# QuerySet不包含資料返回False
3 修改記錄
方法一:QuerySet.update('欄位'='修改的值')
>>> Author.objects.filter(last_name='cu_cow').update(last_name='Ai_cow')
1L
# 修改的前提是先查詢,然後呼叫update(field=val)方法,只有QuerySet集合物件才能呼叫該方法,也就是說通過get(), first(), last()獲取的物件沒有該方法。
方法二:物件賦值
>>> author_obj = Author.objects.filter(last_name='fe_cow').first()
>>> author_obj.last_name = 'Fe_cow'
>>> author_obj.save()
# 不推薦使用,效率低
4 刪除記錄
呼叫delete()方法
delete()方法支援QuerySet
集合物件的刪除,也支援單個物件
的刪除。
>>> Author.objects.filter(last_name='fe_cow').delete()
(1L, {u'apps.Book_authors': 0L, u'apps.Author': 1L})
# 預設就是級聯刪除,對應多對多的表也會刪除
QuerySet
- 通過名字我們也能想到從資料庫查出來的結果一般是一個集合,哪怕只有一個物件,也叫集合。
QuerySet特性
- 可以進行切片,也可以進行遍歷。
>>> Author.objects.filter(id__gt=2)[:2] # 使用切片來獲取
# <QuerySet [<Author: fe cow>, <Author: fe cow>]>
>>> authors = Author.objects.filter(id__gt=2) # 使用for迴圈來獲取
>>> for author in authors:
... print author
# 列印結果如下
# fe cow
# fe cow
# fe cow
# fe cow
- 惰性機制: 只有使用QuerySet時,才會走資料庫。像
.all()
filter()
時,並不會真正執行資料庫查詢,只是翻譯了SQL語句
;當我們執行if xxx
,print xxx
;for xxx in xxx:
這些操作才會執行SQL語句
,進行資料庫查詢。 - 快取機制:
每次
執行了資料庫查詢
後,會將結果放在QuerySet的快取
中,下次在使用QuerySet時, 不會走資料庫,直接從快取中拿取資料。比如:
>>> author = Author.objects.all() # 獲取所有Author QuerySet中的 last_name
>>> for res in author:
... print res.last_name # Ai_cow cow
>>> Author.objects.create(last_name='COW',first_name='FE') # 接下來往資料庫中插入一跳資料
>>>for res in author:
print res.last_name # Ai_cow cow # 發現,已經建立了新的資料,但是表裡面沒有這條資料
# 以上結果證明了QuerySet快取的機制,新新增一條記錄;列印結果沒有發生改變,說明他不會重新走資料庫,而是從快取中獲取資料。
>>> author = Author.objects.all() # 獲取所有Author QuerySet中的 last_name
>>> for res in author:
... print res.last_name # Ai_cow cow COW