數據庫配置
django的數據庫相關表配置在models.py文件中,數據庫的連接相關信息配置在settings.py中
- models.py相關相關參數配置
from django.db import models class userinfo(models.Model): name = models.CharField(max_length=30) email = models.EmailField() memo = models.TextField()
可用的字段:
1、models.AutoField 自增列 = int(11) 如果沒有的話,默認會生成一個名稱為 id 的列,如果要顯示的自定義一個自增列,必須將給列設置為主鍵 primary_key=True。 2、models.CharField 字符串字段 必須 max_length 參數 3、models.BooleanField 布爾類型=tinyint(1) 不能為空,Blank=True 4、models.ComaSeparatedIntegerField 用逗號分割的數字=varchar 繼承CharField,所以必須 max_lenght 參數 5、models.DateField 日期類型 date 對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次創建添加,之后的更新不再改變。 6、models.DateTimeField 日期類型 datetime 同DateField的參數 7、models.Decimal 十進制小數類型 = decimal 必須指定整數位max_digits和小數位decimal_places 8、models.EmailField 字符串類型(正則表達式郵箱) =varchar 對字符串進行正則表達式 9、models.FloatField 浮點類型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 長整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串類型(ip4正則表達式) 13、models.GenericIPAddressField 字符串類型(ip4和ip6是可選的) 參數protocol可以是:both、ipv4、ipv6 驗證時,會根據設置報錯 14、models.NullBooleanField 允許為空的布爾類型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 減號、下划線、字母、數字 18、models.SmallIntegerField 數字 數據庫中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正則表達式 22、models.BinaryField 二進制 23、models.ImageField 圖片 24、models.FilePathField 文件
字段相關參數:
1、null=True 數據庫中字段是否可以為空 2、blank=True django的 Admin 中添加數據時是否可允許空值 3、primary_key = False 主鍵,對AutoField設置主鍵后,就會代替原來的自增 id 列 4、auto_now 和 auto_now_add auto_now 自動創建---無論添加或修改,都是當前操作的時間 auto_now_add 自動創建---永遠是創建時的時間 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默認值 8、verbose_name Admin中字段的顯示名稱 9、name|db_column 數據庫中的字段名稱 10、unique=True 不允許重復 11、db_index = True 數據庫索引 12、editable=True 在Admin里是否可編輯 13、error_messages=None 錯誤提示 14、auto_created=False 自動創建 15、help_text 在Admin中提示幫助信息 16、validators=[] 17、upload-to
- settings.py相關配置
數據庫連接配置:
DATABASES = { 'default': { #'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'ENGINE': 'django.db.backends.sqlite3', #添加數據庫引擎;選項['postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle']. 'NAME': 'F:/TestPython/blog/blog/db/data.db', # 數據庫文件的路徑. # The following settings are not used with sqlite3: # 下面的配置不適用於sqlite3: 'USER': '', # 數據庫登陸用戶名 'PASSWORD': '', # 數據庫登陸密碼 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. # 主機名 'PORT': '', # Set to empty string for default. # 端口號 } }
注冊app:
在settings里的INSTALLED_APPS里面加上你的app名字
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
生成數據庫表
python manage.py makemigrations # 生成一個數據庫結構migrations里面一個表 python manage.py migrate # 根據migrations里面的表來創建數據庫
將app的數據庫注冊到admin
在app01下面的admin.py寫入以下內容:
from django.contrib import admin # Register your models here. # 導入app01的數據庫模塊 from app01 import models # 注冊咱們創建的類,通過他來訪問 admin.site.register(models.UserInfo)
數據庫相關操作
增刪改查
# 插入數據: UserInfo.objects.create(name='rain',password='123',email='rain@163.com') # 刪除數據: UserInfo.objects.filter(name='rain').delete() # 修改數據: UserInfo.objects.filter(name='rain').update(name='Rain1') # 查找數據: UserInfo.objects.filter(name='rain') UserInfo.objects.all() UserInfo.objects.all()[:10] # 切片操作,獲取10個人,不支持負索引,切片可以節約內存 UserInfo.objects.get(name='rain') #查找所有 models.UserInfo.objects.all() #查找指定條件 models.UserInfo.objects.filter(age=18) #查找第一個 models.UserInfo.objects.filter(age=18).first() #查找所有並且顯示出來 user_list_obj = models.UserInfo.objects.all() for line in user_list_obj: print(line.username,line.age)
進階操作
- 利用雙下划線將字段和對應的操作連接起來
# 獲取個數 models.Tb1.objects.filter(name='seven').count() # 大於,小於 models.Tb1.objects.filter(id__gt=1) # 獲取id大於1的值 models.Tb1.objects.filter(id__lt=10) # 獲取id小於10的值 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 # in models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於11、22、33的數據 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains models.Tb1.objects.filter(name__contains="ven") models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 models.Tb1.objects.exclude(name__icontains="ven") # range models.Tb1.objects.filter(id__range=[1, 2]) # 范圍bettwen and # 其他類似 startswith,istartswith, endswith, iendswith, # order by models.Tb1.objects.filter(name='seven').order_by('id') # asc models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset models.Tb1.objects.all()[10:20] # group by from django.db.models import Count, Min, Max, Sum models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
- F和Q操作
# F 使用查詢條件的值 from django.db.models import F models.Tb1.objects.update(num=F('num')+1) # Q 構建搜索條件 from django.db.models import Q con = Q() q1 = Q() q1.connector = 'OR' q1.children.append(('id', 1)) q1.children.append(('id', 10)) q1.children.append(('id', 9)) q2 = Q() q2.connector = 'OR' q2.children.append(('c1', 1)) q2.children.append(('c1', 10)) q2.children.append(('c1', 9)) con.add(q1, 'AND') con.add(q2, 'AND') models.Tb1.objects.filter(con) from django.db import connection cursor = connection.cursor() cursor.execute("""SELECT * from tb where name = %s""", ['Lennon']) row = cursor.fetchone()
連表操作
連表關系:
- 一對多,models.ForeignKey(ColorDic)
- 一對一,models.OneToOneField(OneModel)
- 多對多,authors = models.ManyToManyField(Author)
應用場景:
- 一對一:在某表中創建一行數據時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了)。 例如:原有含10列數據的一張表保存相關信息,經過一段時間之后,10列無法滿足需求,需要為原來的表再添加5列數據。
- 一對多:當一張表中創建一行數據時,有一個單選的下拉框(可以被重復選擇)。 例如:創建用戶信息時候,需要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等。
- 多對多:在某表中創建一行數據是,有一個可以多選的下拉框。 例如:創建用戶信息,需要為用戶指定多個愛好。
一對多
- 數據庫表:models.py UserType存放用戶類型,UserInfo存放用戶信息
from django.db import models # Create your models here. class UserType(models.Model): caption = models.CharField(max_length=32) # 超級管理員,普通用戶,游客,黑河 def __str__(self): return self.caption class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey('UserType')
- 創建有外鍵的數據
#方法一:需要進行兩次數據庫操作,不推薦 UserInfo.objects.create(user='test',pwd='123',user_type=UserType.objects.get(id=1)) #方法二:利用外鍵關系進行直接插入值,此時user_type代指的就是usertype表 UserInfo.objects.create(user='test',pwd='123',user_type_id=1) >>> from app01 import models >>> models.UserInfo.objects.create(user='test',pwd='123',user_type=models.UserType.objects.get(id=1)) <UserInfo: UserInfo object> >>> models.UserInfo.objects.create(user='asdasdadas',pwd='123',user_type_id=3) <UserInfo: UserInfo object>
- 數據:


- 查找
1.根據用戶,查找用類型
>>> models.UserInfo.objects.filter(user="test")[0].user_type.caption '管理員' 此時user_type對應的就是usertype的表,所以直接使用.caption就可以拿到數據
2.根據用戶類型查找用戶
#方法一:先查找出用戶類型對應的user_type的id,然后再去userinfo表中查找id對應的用戶 >>> role_id = models.UserType.objects.get(caption='管理員').id >>> role_id 1 >>> models.UserInfo.objects.filter(user_type=role_id).values('user','pwd') <QuerySet [{'pwd': '123', 'user': '張三'}, {'pwd': '123', 'user': 'test2'}, {'pwd': '123', 'user': 'test'}]> #方法二:使用雙下划線進行一次連表操作 >>> models.UserInfo.objects.filter(user_type__caption="管理員") <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> >>> sql[0].user '張三' >>> sql[0].pwd '123' >>> sql[0].user_type.caption '管理員' >>> sql[0].user_type.id 1 繼續封裝,同時取用戶的所有信息: >>> sql = models.UserInfo.objects.filter(user_type__caption="管理員").values('user','pwd','user_type__id','user_type__caption') >>> sql <QuerySet [{'user_type__id': 1, 'pwd': '123', 'user': '張三', 'user_type__caption': '管理員'}, {'user_type__id': 1, 'pwd': '123', 'user': 'test2', 'user_type__caption': '管理員'}, {'user_type__'pwd': '123', 'user': 'test', 'user_type__caption': '管理員'}]> 打印sql語句: >>> print(sql.query) SELECT "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_usertype"."caption" FROM "app01_userinfo" INNER JOIN "app01_usertype" ON ("app01_userinfo"."user_type_id" = "app01_usertype"."id") WHERE "app01_usertype"."caption" = 管理員
跨多張表進行操作,如果UserType表中還有外鍵指向另一張表的主鍵,怎么查呢?
新的表結構如下:
from django.db import models # Create your models here. class UserType(models.Model): caption = models.CharField(max_length=32) # 超級管理員,普通用戶,游客,黑河 s = models.ForeignKey('something') def __str__(self): return self.caption class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey('UserType') class something(models.Model): name = models.CharField(max_length=32)
查詢:
models.UserInfo.objects.filter(user_type__s__name="一些條件值"
這是跨兩張表,跨三張表、四張表都這樣
多對多
- 表結構: 一個girl表、一個boy表,還一個boy_girl的關系表
class Girl(models.Model): name = models.CharField(max_length=32) b = models.ManyToManyField('Boy') class Boy(models.Model): name = models.CharField(max_length=32)
PS:多對多關系需要三張表,兩張數據表,一張關系表,但是在django 中如果使用ManyToManyField的話,不需要在指定第三張表,默認django會創建。當然,如果不使用該字段的話,也可以手動指定第三張表,然后使用models.ForeignKey做外鍵關聯
- 添加數據
添加數據到關系表:
女孩跟男孩建立關系 正向操作 >>> G = models.Girl.objects.get(id=1) >>> g = models.Girl.objects.get(id=1) >>> girl = models.Girl.objects.get(id=1) >>> boy = models.Boy.objects.get(id=3) >>> girl.name 'fuzj3' >>> boy.name 'fuzj2' #使用對象建立關系 >>> girl.b.add(boy) #此時的b時多對多的字段 >>> bs = models.Boy.objects.all() #獲取男孩的所有對象,返回數組 >>> g.b.add(*bs) #批量將關系插入到關系表 #使用主鍵值建立關系 >>> girl = models.Girl.objects.get(id=3) >>> girl.b.add(3) >>> bs_list = [1,4,5] >>> girl.b.add(*bs_list) 男孩跟女孩建立關系 反向操作 >>> boy = models.Boy.objects.get(id=1) >>> boy <Boy: Boy object> >>> boy.girl_set.add(3)



-
刪除
remove() 刪除
clear() 清空
>>> g1 = models.Girl.objects.get(id=1) #獲取一個女孩對象 >>> g1.b.remove(2) #單個刪除一個關系 >>> g1.b.remove(*[3,4]) #批量刪除多個關系 >>> g1.b.clear() #清空本對象對應的所有關系
-
查詢
支持all() filer()等操作
1.通過女孩查找男孩(正向查找) >>> models.Girl.objects.filter(name='fuzj2').values('id','name','b__name') <QuerySet [{'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj'}, {'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj2'}, {'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj3'}, {'name': 'fuzj2', 'id': 3, 'b__name': None}]> 'b__name'中 b此時代指的關系表,所以b__name 就是跨到了boy表,。此時相當於直接跨了兩張表 2. 通過男孩查找女孩(反向查找) >>> models.Boy.objects.filter(name='fuzj').values('id','name','girl__name') <QuerySet [{'name': 'fuzj', 'id': 1, 'girl__name': 'fuzj2'}]> 'girl__name' 中,girl是boy表中隱藏的字段,代指的是和girl的關系表,所以girl__name就跨到了girl表
-
修改
默認django不支持修改操作,如果實現修改操作,只能是先刪除,然后再創建,顯然這個效率不是很高。所以,我們可以通過原生的sql語句進行操作
from django.db import connection cursor = connection.cursor() cursor.execute("update tbname set girl_id = '3' where boy_id = %s",[3])
中間件
中間件定義:
-
中間件是一個、一個的管道,如果相對任何所有的通過Django的請求進行管理都需要自定義中間件
-
中間件可以對進來的請求和出去的請求進行控制
-
中間件是一類。

由上圖可知,中間件是位於wsgi和路由系統中間的環節。用戶請求和和回應請求都會經過中間件。
看下面的代碼在settings里中間件的類:
MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
當有請求過來的時候,默認從上倒下執行!然后在返回的時候從下面在返回回去
自定義中間件
中間件中可以定義四個方法,分別是:
- process_request(self,request)
- process_view(self, request, callback, callback_args, callback_kwargs)
- process_exception(self, request, exception) 這個方法只有在出現錯誤的時候才會觸發
- process_response(self, request, response)
- process_template_response(self,request,response) 這個方法只有在返回對象中有render方法的時候才執行,如render_to_response('/index/')
以上方法的返回值可以是None和HttpResonse對象,如果是None,則繼續按照django定義的規則向下執行,如果是HttpResonse對象,則直接將該對象返回給用戶。

- 創建中間件腳本
在django的的project目錄下創建一個middleware目錄,並創建一個md.py的腳本,內容如下:
class Testmiddle: def process_request(self,request): print 'Testmiddle process_request' def process_view(self, request, callback, callback_args, callback_kwargs): print 'Testmiddle process_view' def process_exception(self, request, exception): pass def process_response(self, request, response): print 'Testmiddle process_response' return response class Nextmiddle: def process_request(self,request): print 'Nextmiddle process_request' def process_view(self, request, callback, callback_args, callback_kwargs): print 'Nextmiddle process_view' def process_exception(self, request, exception): pass def process_response(self, request, response): print 'Nextmiddle process_response' return response
- 注冊中間件
修改settings.py文件,在MIDDLEWARE_CLASSES中添加我們創建的中間件
MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'middleware.middle.Testmiddle', 'middleware.middle.Nextmiddle', ]
- 設置url 略
- 測試:
Testmiddle process_request
Nextmiddle process_request
Testmiddle process_view
Nextmiddle process_view
This app01 Views.index
Nextmiddle process_response
Testmiddle process_response
從輸出結果可以看出:
他是先執行Testmiddle 的request 方法又執行了Nextmiddle的 process_request方法, 然后在執行Testmiddle的view方法,Nextmiddle的view方法
注意:django版本1.10以后,會報如下錯誤:

解決如下:
from django.utils.deprecation import MiddlewareMixin class Testmiddle(MiddlewareMixin): def process_request(self,request): print 'Testmiddle process_request' def process_view(self, request, callback, callback_args, callback_kwargs): print 'Testmiddle process_view' def process_exception(self, request, exception): pass def process_response(self, request, response): print 'Testmiddle process_response' return response class Nextmiddle(MiddlewareMixin): def process_request(self,request): print 'Nextmiddle process_request' def process_view(self, request, callback, callback_args, callback_kwargs): print 'Nextmiddle process_view' def process_exception(self, request, exception): pass def process_response(self, request, response): print 'Nextmiddle process_response' return response
注意:
* 老版本中在中間件中如果某個中間件類的方法返回的不是none,則后面的中間件不會再處理請求,也不會到達路由系統,而是直接到第一個process_response,開始所有的process_response處理
* 新版本中在中間件中如果某個中間件類的方法返回的不是none,則后面的中間件不會再處理請求,也不會到達路由系統,而是直接到最后一個process_response處理,然后返回給客戶端