1:數據庫:python
2:MySQL驅動程序的安裝mysql
3:Django配置鏈接數據庫sql
4:在Django中操做數據庫數據庫
(1)原生SQL語句操做django
(2)ORM模型操做緩存
5:ORM模型的介紹安全
6:建立一個ORM模型並映射模型到數據庫中數據結構
7:模型經常使用的屬性app
(1)經常使用的Field字段框架
(2)Field字段經常使用的參數
(3)模型中Meta的配置
8:外鍵
9:表關係
(1)一對一
(2)一對多(多對一)
(3)多對多
10:模型的操做
(1)數據的增刪改查
(2)聚合函數
(3)aggregate和annotate的區別
(4)F表達式和Q表達式
11:查詢集(QuerySet)
12:ORM模型遷移
-------------------------------------------------------------------------------------------------------------------------------
1數據庫:簡而言之就是存放數據的一個庫,用戶能夠對數據進行增刪改查;是網站重要的一個組成部分,只有提供了數據庫,網站才能動態的展現。經常使用的數據庫有MySQL,Oracle等。
2MySQL驅動程序的安裝:咱們使用Django來操做mysql,實際上底層使用的仍是python;所以若是咱們想要操做數據庫首先要安裝一個驅動;python3中有多個驅動可供選擇以下;
(1)MySql-python :也就是MySQLdb 。是對C語言操做mysql的一個簡單封裝;只支持python2,不支持python3,運行速度最快。
(2)mysqlclient:是MySql-python的另外一個分支,支持python3。
(3)pymsql:純python實現的一個驅動,效率不高,能夠和python無縫鏈接。
(4)mysql-connector-python:mysql官方推出的,純python開發的,效率不高
本文使用的是mysqlclient: 安裝方式: pip install mysqlclient
3:Django配置鏈接數據庫:在操做數據庫以前須要Django先鏈接上數據庫,不須要單首創建一個鏈接對象,只須要在setting中作好相關的配置便可。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', #數據庫引擎(mysql仍是Oracle) 'NAME': "my01", #數據庫的名字 "USER":"root", #數據庫的用戶名 "PASSWORD":"qwe123", #數據庫密碼 "HOST":"localhost", #數據庫的主機地址 "PORT":"3306" #數據庫的端口號 } }
4:在Django中操做數據庫:Django操做數據庫有兩種方式。第一種是原生的SQL語句操做,另外一種是ORM模型操做
(1)原生SQL語句操做
缺點:(1)重複利用率不高(2)不易修改(3)安全問題(SQL注入)
(2)ORM模型操做
5:ORM模型的介紹
(1)ORM,全稱Object Relational Mapping,中文叫作對象-關係映射。
(2)經過ORM咱們能夠經過類的方式來操做數據庫,經過把類映射成表,把實例映射爲行,把屬性映射爲字段;ORM在執行對象操做的時候最終仍是會把對應的操做轉換爲SQL語句。
6:建立一個ORM模型並映射模型到數據庫中
第一步:建立一個User模型類(在數據庫中的表現:類--表名(app的名字_類名(小寫)),屬性--字段,實例-行)
class User(models.Model): username = models.CharField(max_length=10) telephone = models.CharField(max_length=11) email = models.EmailField() sex = models.BooleanField()
第二步:執行makemigrations [app_name] #後面能夠跟APP的名字,生成遷移腳本文件
第三步:執行migrate [app_name] #映射到數據庫中
7:模型經常使用的屬性
(1)經常使用的Field字段
AutoField:int類型,自動增加
BigAutoField:相似於AutoField,範圍1-9223372036854775807
BooleanField:tinyint類型,True/False
CharField: varchar類型,使用時必須指定最大長度,即max_length參數必須傳遞
DateField: 日期類型;兩個參數auto_now:每次保存的時候都是用當前的時間,好比記錄一個記錄修改的日期;auto_now_add:在數據第一次建立的時候用當前的時間,好比記錄第一次入庫的時間。
DateTimeField:日期時間類型;不只能夠存儲日期還能夠存儲時間。兩個參數(auto_now和auto_now_add)
TimeField:時間類型;
EmailField:varchar類型;最大長度254
FileField:用來存儲文件的
FloatField:浮點類型
ImageField:存儲圖片
IntegerField:整型,-2147483648 - 2147483647
BigIntegerField:大整形,
PositiveIntegerField:正整型;0-2147483647
SmallIntegerField:小整型,-32768 - 32767
TextField:大量的文本類型,longtext
UUIDField:存儲uuid格式的字符串,是一個32位的全球惟一的字符串,通常作主鍵
URLField:存儲url格式的字符串,max_length默認是200
(2)Field字段經常使用的參數
null:表示映射爲表的時候是否能夠爲空,默認爲False(不能爲空);在使用字符串相關的Field時(CharField、TextField)通常保持默認的False,由於即使是Flase,Django也會建立一個空字符串 " "做爲默認值傳遞進去,若是再設置爲True的話,就會用null來存儲空值,默認值就變爲了兩個(""和null)
blank:表示驗證的時候是否能夠爲空,默認是False。(和null的區別:null是一個數據庫級別的,blank是表單驗證級別的)
db_column:表示字段在數據庫中的名字
default:默認值,能夠是一個值或者函數,不支持lambda表達式,而且不支持列表、字典。集合等可變的數據結構
primary_key:默認值false,是否爲主鍵
unique:是否惟一,通常手機號或者郵箱用
(3)模型中Meta的配置
對於一些模型級別的配置,咱們能夠在模型中定義一個類,叫作Meta,而後在這個類中添加一些類屬性來控制模型。好比在映射到數據庫中表的名字使用本身定義的。
from django.db import models class User(models.Model): username = models.CharField(max_length=10) telephone = models.CharField(max_length=11) email = models.EmailField() sex = models.BooleanField(db_column="sex_a") create_time = models.DateTimeField(auto_now_add=True) class Meta: db_table = "User", //表的名字 ordering = ["create_time"] //在查找數據的時候根據添加的時間排序
8:外鍵
若是一張表中非主鍵的某個字段指向了另外一張表中的主鍵,那麼這個字段就是該表的外鍵。
外鍵的做用是:防止一張表過於複雜(好比一個需求是一個名字對應一張照片,若是保存在同一種表中數據可能有些亂,最好是分開兩張表,一種保存名字,另外一張保存圖片,同時兩張表又有一種制約,能夠經過名字找到這張圖片,或者經過圖片找到這個名字)。
在mysql中,表有兩種引擎,一種是InnoDB,支持外鍵的使用;另外一種是myisam,暫時不支持外鍵的使用。
Django中的外鍵使用ForeignKey(to,on_delete,**options),第一個參數是引用的是哪一個模型,第二個參數是使用外鍵引用的模型被刪除的時候,這個字段該如何處理。
注意:若是引用的模型在另外一個APP中,則第一個參數須要添加app_name.模型名;若是引用的是模型自己本身能夠用self或者模型本身的名字
from django.db import models class User(models.Model): //用戶模型 username = models.CharField(max_length=10) password = models.CharField(max_length=20) class Article(models.Model): //文章模型 title = models.CharField(max_length=20) content = models.TextField() author = models.ForeignKey("User",on_delete=models.CASCADE) //外鍵 category = models.ForeignKey("login.Tags",on_delete=models.CASCADE) //另外一個app,login中model的Tags模型 class Comment(models.Model): content = models.TextField() origin_comment = models.ForeignKey("self",on_delete=models.CASCADE,null=True) //外鍵是模型本身 # origin_comment = models.ForeignKey("Comment",on_delete=models.CASCADE,null=True)
外鍵刪除操做:
若是一個模型引用了外鍵,在對方那個模型被刪除掉,該進行什麼樣的操做;經過on_delete來指定:
CASCADE:級聯操做,若是外鍵對應的那條數據被刪除,那麼這條數據也被刪除。
PROTECT:受保護,即只要這條數據引用了外鍵的那條數據,那麼就不能刪除外鍵的那條數據。
SET_NULL:設置爲空,若是外鍵的那條數據被刪除,那麼本條數據設置爲空,前提是這個字段能夠爲空。
SET_DEFAULT:設置爲默認值,若是外鍵的那條數據被刪除,那麼本條數據設置默認值,前提是要指定一個默認值。
SET():若是外鍵那條數據被刪除,則調用set函數的值,做爲外鍵的值
DO_NOTHING:不採起任何行爲,看數據庫級別的約束。
9:表關係:表之間的關係都是經過外鍵進行關聯的,三種關係,一對一,一對多(多對一),多對多
(1)一對一
應用場景:一個用戶和一個用戶信息表
實現方式:經過OneToOneField來實現
(2)一對多(多對一)
應用場景:好比做者和文章之間的關係,一個做者能夠有多篇文章,可是一篇文章只能有一個做者
實現方式:一對多或者多對一,都是經過ForeignKey來實現的
(3)多對多
應用場景:好比文章和標籤之間的關係;一篇文章能夠有多個標籤,一個標籤能夠被多篇文章引用
實現方式:經過ManyToManyField來實現
表之間的查詢方式:related_name和related_query_name;咱們依然使用上面的User模型和Article模型來舉例:
(1)若是咱們想要經過文章獲取該做者:
article = Article.objects.first() //獲取這篇文章
print(article.author.username) //直接經過author獲取做者
(2)若是想要經過做者獲取其下的全部文章方式有兩種:
#方式一:Django默認每一個主表都有一個默認的屬性來獲取子表的信息,這個屬性就是子表模型的小寫加上_set(),默認返回一個querydict對象,能夠進一步操做 author = User.objects.first() print(author.article_set.all()) #方式二:在默認中添加related_name,之後主表直接經過這個值來獲取子表的信息,獲得的也是一個querydict對象。 author = models.ForeignKey("User",on_delete=models.CASCADE,related_name="article") #咱們能夠直接使用這個值 print(author.article.first().title)
(3)relate_name=「+」,表示禁止使用反向查詢
10:模型的操做:在ORM框架中,全部的模型操做其實都是映射到數據庫中一條數據的操做,所以模型操做也就是數據庫表中數據的操做。
(1)數據的增刪改查
一:以上面表User爲例:
(1)增長數據:
User.objects.create(username="王三",password="123")
(2)查數據:(all(),get(),filter())
#查找全部的數據:返回的是一個queryset集合,沒有知足條件返回空列表 users = User.objects.all() for user in users: print(user.username) print(users) #查找單個的對象,返回一個對象,沒有知足條件時報錯 user = User.objects.get(username="張帆") print(user.username) #數據過濾查找filter;查詢的時候有時須要對數據進行過濾再查詢,返回全部知足條件的QuerySet集合 user = User.objects.filter(username="張帆",password="213123") print(user) #數據排序;查找數據的時候都是無序的,若是想對某個數據進行排序使用order_by,反向排序加個減號 users = User.objects.order_by("username")
(3)改數據:
#修改數據:獲取這條數據,對屬性修改,而後保存 user = User.objects.get(username="張帆") user.username = "李四" user.save()
(4)刪除數據
#刪除數據;獲取數據,而後執行delete()函數 user = User.objects.get(username="李四") user.delete()
二:查詢條件:查找的時候通常使用filter,get,exclude三個方法來實現,咱們能夠對其傳遞不一樣的參數,來實現不一樣的需求。格式(約束條件_查找條件)
第一組:精確和like
exact:使用精確 = 進行查找 ; User.objects.get(id_exact = 2),若是提供一個None值,sql層面被解釋爲null
iexact: 使用like進行查找
第二組:包含(title_contains = "hello")
contains:大小寫敏感
icontains:大小寫不敏感
第三組:提供包含在容器中值,容器能夠是列表,元組,任意一個可迭代的對象
in:User.objects.get(id_in=[1,2,3])
也能夠傳遞一個queryset對象進去:獲取標題中包含張三的文章
username = User.objects.filter(username_contains = "張三")
user = Article.objects.filter(title_in = username)
第四組:(id__gt = 3)
gt:大於
gte:大於等於
lt:小於
lte:小於等於
第五組:判斷某個字段是否以某個值爲開始(結束) (title_startwith = "hello")
startwith:
istartwith:
endswith:
iendswith:
第六組:
range:判斷是否在某個區間;(create_time = range(start,end))
第七組:根據時間查詢
date:年月日 (create_time_date=date(2018,3,23))
year:年(create_time_year = 2108)
month:月(同上)
day:天(同上)
wek_day:星期幾(1表示星期天,7表示星期六)
time:時分秒(create_time= datetime_time(2,2,2)),2點2分2秒
第八組:是否爲空
isnull:(title_isnull = False) 不爲空
第九組:正則
regex:大小寫敏感:(title_regex=r"hello")
iregex:大小寫不敏感:(title_regex=r"hello")
三:關聯表查詢
好比有兩個模型,一個是User,一個是Article;想要獲取文章標題中帶有「中國」的用戶
user = User.objects.filter(article_title_contains = "hello")
(2)聚合函數:聚合函數是同aggregate方法來實現的。
(1)Avg:求平均值
(2)Count:獲取指定對象的個數
(3)Max和Min:獲取最大值最小值
(4)Sum:求和
假設有這樣一個模型:
class BookOrder(models.Model): book_name = models.CharField(max_length=12) price = models.FloatField()
數據表爲:
# result = BookOrder.objects.aggregate(Avg("price")) //全部書的平均價格,名字規則爲field_avg組成 result = BookOrder.objects.aggregate(book_price = Avg("price")) //給這個價格指定一個名字 print(result) result = BookOrder.objects.aggregate(book_num = Count("id")) //求全部的書 print(result) result = BookOrder.objects.aggregate(book_price_max = Max("price")) //求最大值 print(result) result = BookOrder.objects.aggregate(book_price_min=Min("price")) //求最小值 print(result) result = BookOrder.objects.aggregate(books_price = Sum("price")) //求最和 print(result)
(3)aggregate和annotate的區別
(4)F表達式和Q表達式
F表達式是用來優化ORM模型操做數據庫的,並不會馬上去數據庫中獲取數據,而是在生成SQL語句的時候,動態的獲取傳給F表達式的值
BookOrder.objects.update(price = F("price")+100) //更新圖書的價格
Q表達式:通常查詢條件比較多的時候使用,可使用與或非,&,|,~
books = BookOrder.objects.filter(Q(id=3) | Q(book_name__contains="記"))
11:查詢集(QuerySet)
(1)查詢集就是經過查詢後獲得的一個對象集合。
Django中查詢操做都是經過 模型名.objects的方式進行;這個objects是一個Manager對象,而這個Manager這個類是一個空殼的類,它自己沒有任何的屬性和方法;都是經過Python從QuerySet類中動態的添加過來的。
class Manager(BaseManager.from_queryset(QuerySet)): pass class BaseManager: @classmethod def from_queryset(cls, queryset_class, class_name=None): if class_name is None: class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__) return type(class_name, (cls,), { '_queryset_class': queryset_class, **cls._get_queryset_methods(queryset_class), })
class QuerySet:
"""Represent a lazy database lookup for a set of objects."""
def __init__(self, model=None, query=None, using=None, hints=None):
self.model = model
self._db = using
self._hints = hints or {}
self.query = query or sql.Query(self.model)
self._result_cache = None
self._sticky_filter = False
self._for_write = False
self._prefetch_related_lookups = ()
self._prefetch_done = False
self._known_related_objects = {} # {rel_field: {pk: rel_obj}}
self._iterable_class = ModelIterable
self._fields = None
............(後面省略)
(2)兩大特性:
惰性執行:建立查詢集不會馬上執行,只到調用數據時纔會去數據庫中查詢,調用數據包括:迭代,使用步長作切片操做,調用len函數,調用list函數,判斷
緩存:使用同一個查詢集,第一次會發生數據庫查詢,而後django會把數據緩存起來,之後再使用的時候不會去數據庫查詢而是直接使用
(3)經常使用的API:
1.filter:將知足條件的數據提取出來,返回一個queryset對象
2.exclude:排除知足條件的對象,返回一個queryset對象
3.annotate:
4.order_by:排序(倒序加減號),多個order_by鏈式使用時,會把前面的打亂,之後面的爲準
5.values:規定提取那些字段,返回的是一個字典類型。默認會把全部字段都提取出來
6.values_list:同上,不過返回的是一個元組
7.defer:過濾掉一些字段,返回的是一個模型
8.only:只保留這個字段(和上面相反)
9.all:返回queryset對象
10.select_related:
11.prefetch_related:
12.get:只返回一條知足條件的數據,若是是多條或者沒有都會報錯
13.create:建立一條數據,並保存
14.get_or_create:若是數據庫中存在這個數據就返回,不存在就建立;返回一個元組(第一個參數是這個對象,第二個參數是boolean類型)
15.bulk_create:一次建立多個數據;bulk_create([book_name="111",book_name="222"])
16.count:獲取數據的個數,比len函數高效
17.first和last:返回queryset中的第一條和最後一條
18.aggregate:使用聚合函數
19.exists:判斷是否存在
20.distinct:去掉重複的數據;
21.update:更新
22.delete:刪除數據
23.切片:Books.objects.all()[1:3];切片不是把數據都提取出來再作切片,而是在底層直接使用LIMIE和OFFSET
12:ORM模型遷移
(1)makemigrations:將模型生成遷移腳本
app_label:後面跟一個或者多個app,只會針對這幾個app生成遷移腳本,若是沒有寫就是針對全部都生成
--name:給這個遷移腳本生成一個名字
--empty:生成一個空的遷移腳本
(2)migrate:將生成的遷移腳本映射到數據庫中
app_label:規定那幾個app
app_label migrationname;將某個app下指定名字的migration文件映射到數據庫中
--fake:能夠將指定的遷移腳本文件名字添加到數據庫中,可是並不會把遷移腳本文件轉換爲sql語句,修改數據庫中的表
--fake-initial:將第一次生成的遷移文件版本號記錄在數據庫中,但並不會執行遷移腳本
(3)showmigrations:查看某個app的遷移文件;若是後面沒有app將查看全部的
(4)sqlmigrate:查看某個遷移文件映射到數據庫中轉換的SQL語句