Django 框架十分強大,自帶數據庫操做功能。Django 跟 SQLAchemy 同樣,也是經過ORM(Object Relational Mapping,關係對象映射)的方式對數據庫進行操做,django中遵循 Code Frist (根據代碼中定義的類來自動生成數據庫表)的原則。html
一、在SQLite中建立表python
1.一、在app中的models.py中先寫類:mysql
from django.db import models # Create your models here. class UserInfo(models.Model): # id列,Django框架會默認生成id(自增,主鍵),也能夠經過AutoField類型自定義主鍵,不過Django框架默認生成ID列會失效 # 用戶名列,字符串類型,最大長度長度 username = models.CharField(max_length=32) password = models.CharField(max_length=64)
1 AutoField(Field) 2 - int自增列,必須填入參數 primary_key=True 3 4 BigAutoField(AutoField) 5 - bigint自增列,必須填入參數 primary_key=True 6 7 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 8 from django.db import models 9 10 class UserInfo(models.Model): 11 # 自動建立一個列名爲id的且爲自增的整數列 12 username = models.CharField(max_length=32) 13 14 class Group(models.Model): 15 # 自定義自增列 16 nid = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=32) 18 19 SmallIntegerField(IntegerField): 20 - 小整數 -32768 ~ 32767 21 22 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23 - 正小整數 0 ~ 32767 24 IntegerField(Field) 25 - 整數列(有符號的) -2147483648 ~ 2147483647 26 27 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28 - 正整數 0 ~ 2147483647 29 30 BigIntegerField(IntegerField): 31 - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 32 33 自定義無符號整數字段 34 35 class UnsignedIntegerField(models.IntegerField): 36 def db_type(self, connection): 37 return 'integer UNSIGNED' 38 39 PS: 返回值爲字段在數據庫中的屬性,Django字段默認的值爲: 40 'AutoField': 'integer AUTO_INCREMENT', 41 'BigAutoField': 'bigint AUTO_INCREMENT', 42 'BinaryField': 'longblob', 43 'BooleanField': 'bool', 44 'CharField': 'varchar(%(max_length)s)', 45 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 46 'DateField': 'date', 47 'DateTimeField': 'datetime', 48 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 49 'DurationField': 'bigint', 50 'FileField': 'varchar(%(max_length)s)', 51 'FilePathField': 'varchar(%(max_length)s)', 52 'FloatField': 'double precision', 53 'IntegerField': 'integer', 54 'BigIntegerField': 'bigint', 55 'IPAddressField': 'char(15)', 56 'GenericIPAddressField': 'char(39)', 57 'NullBooleanField': 'bool', 58 'OneToOneField': 'integer', 59 'PositiveIntegerField': 'integer UNSIGNED', 60 'PositiveSmallIntegerField': 'smallint UNSIGNED', 61 'SlugField': 'varchar(%(max_length)s)', 62 'SmallIntegerField': 'smallint', 63 'TextField': 'longtext', 64 'TimeField': 'time', 65 'UUIDField': 'char(32)', 66 67 BooleanField(Field) 68 - 布爾值類型 69 70 NullBooleanField(Field): 71 - 能夠爲空的布爾值 72 73 CharField(Field) 74 - 字符類型 75 - 必須提供max_length參數, max_length表示字符長度 76 77 TextField(Field) 78 - 文本類型 79 80 EmailField(CharField): 81 - 字符串類型,Django Admin以及ModelForm中提供驗證機制 82 83 IPAddressField(Field) 84 - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 85 86 GenericIPAddressField(Field) 87 - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 88 - 參數: 89 protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 90 unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓刺功能,須要protocol="both" 91 92 URLField(CharField) 93 - 字符串類型,Django Admin以及ModelForm中提供驗證 URL 94 95 SlugField(CharField) 96 - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) 97 98 CommaSeparatedIntegerField(CharField) 99 - 字符串類型,格式必須爲逗號分割的數字 100 101 UUIDField(Field) 102 - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 103 104 FilePathField(Field) 105 - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 106 - 參數: 107 path, 文件夾路徑 108 match=None, 正則匹配 109 recursive=False, 遞歸下面的文件夾 110 allow_files=True, 容許文件 111 allow_folders=False, 容許文件夾 112 113 FileField(Field) 114 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 115 - 參數: 116 upload_to = "" 上傳文件的保存路徑 117 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 118 119 ImageField(FileField) 120 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 121 - 參數: 122 upload_to = "" 上傳文件的保存路徑 123 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 124 width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) 125 height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) 126 127 DateTimeField(DateField) 128 - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 129 130 DateField(DateTimeCheckMixin, Field) 131 - 日期格式 YYYY-MM-DD 132 133 TimeField(DateTimeCheckMixin, Field) 134 - 時間格式 HH:MM[:ss[.uuuuuu]] 135 136 DurationField(Field) 137 - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 138 139 FloatField(Field) 140 - 浮點型 141 142 DecimalField(Field) 143 - 10進制小數 144 - 參數: 145 max_digits,小數總長度 146 decimal_places,小數位長度 147 148 BinaryField(Field) 149 - 二進制類型
1 class User(models.Model): 2 name = models.CharField(max_length=32) 3 pwd = models.CharField(max_length=32) 4 #class User(models.Model): 5 # name = models.CharField(max_length=32,db_index=True) 6 # pwd = models.CharField(max_length=32,db_index=True) 7 class Meta: 8 #指定數據庫表名:tb1,若是不指定表名將會默認生成表名:app名稱 + 下劃線 + 類名 9 db_table = "tb1" 10 11 #索引,mysql每一列加上索引就會生成一個文件,所以當上面被註釋的User表生成是mysql數據庫就會生成一個表,兩個文件, 12 #所以不想數據庫生成太多索引文件,又想個別列名可以支持索引查詢,這個時候就須要用到聯合索引, 13 index_together = [ # 聯合索引,只會生成一個索引文件 可是有一個缺點就是,遵循最左前綴模式查詢 14 ("name", 'pwd'), 15 ] 16 17 # 最左前綴的模式: 18 # select * from where name='xx' 19 # select * from where name='xx' and email = 'xx' 20 # select * from where email = 'xx' # 沒法命中索引 21 22 #聯合惟一索引,與上面的聯合索引同樣,就是多了一個列名組合惟一的限制 23 unique_together = (("driver", "restaurant"),) 24 25 #admin中的配置 26 verbose_name = 「name」 #在admin中會將name顯示成names,多加一個「s」 27 verbose_name_plural=「「name」」 #在admin中會將name顯示成name,顯示原生自定義的名字
1 null 數據庫中字段是否能夠爲空 2 db_column 數據庫中字段的列名 3 db_tablespace 4 default 數據庫中字段的默認值 5 primary_key 數據庫中字段是否爲主鍵 6 db_index 數據庫中字段是否能夠創建索引 7 unique 數據庫中字段是否能夠創建惟一索引 8 unique_for_date 數據庫中字段【日期】部分是否能夠創建惟一索引 9 unique_for_month 數據庫中字段【月】部分是否能夠創建惟一索引 10 unique_for_year 數據庫中字段【年】部分是否能夠創建惟一索引 11 12 verbose_name Admin中顯示的字段名稱 13 blank Admin中是否容許用戶輸入爲空 14 editable Admin中是否能夠編輯 15 help_text Admin中該字段的提示信息 16 choices Admin中顯示選擇框的內容,用不變更的數據放在內存中從而避免跨表操做 17 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 想要在HTML中顯示choice中的字段值,而不是數學索引,須要用到{{k.get_帶choices參數的字段_display}}方法 18 19 error_messages 自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息; 20 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 21 如:{'null': "不能爲空.", 'invalid': '格式錯誤'} 22 23 validators 自定義錯誤驗證(列表類型),從而定製想要的驗證規則 24 from django.core.validators import RegexValidator 25 from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ 26 MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 27 如: 28 test = models.CharField( 29 max_length=32, 30 error_messages={ 31 'c1': '優先錯信息1', 32 'c2': '優先錯信息2', 33 'c3': '優先錯信息3', 34 }, 35 validators=[ 36 RegexValidator(regex='root_\d+', message='錯誤了', code='c1'), 37 RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'), 38 EmailValidator(message='又錯誤了', code='c3'), ] 39 )
1.二、在settings.py中註冊app:git
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app1', ]
1.三、在控制檯輸出cmd 命令:sql
python3 manage.py makemigrations #至關於在該app的migrations目錄,記錄下該app下modes.py全部表結構類型的改動(普通增刪改查不記錄) python3 manage.py migrate #將剛剛對於表結構的改動做用至數據庫
二、在MySQL中建立表數據庫
2.一、在上面步驟1.1 先寫類、1.2 註冊app的基礎上,在與Django project中與project同名目錄下的__init__.py文件中配置以下代碼:django
import pymysql pymysql.install_as_MySQLdb()
注:# 因爲Django內部鏈接MySQL時使用的是MySQLdb模塊,而python3中還無此模塊,因此須要使用pymysql來代替json
2.2,在settings.py中更改數據庫配置session
#將原先數據庫配置註釋,使用mysql配置 # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test1', # 數據庫名稱 'USER': 'root', # 用戶名 'PASSWORD': '123456', # 密碼 'HOST': 'localhost', # ip 'PORT': '3306', # 端口 } }
2.三、執行命令app
python3 manage.py makemigrations python3 manage.py migrate
注:配置好數據庫爲mysql後,從新啓動Django工程,若是報錯mysql django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required;的話, 這是由於 mysql client 端的版本小於1.3.3。最簡單的解決辦法是:
#找到Django的安裝路徑的mysql配置下的base.py,如C:\Python36\Lib\site-packages\django\db\backends\mysql\base.py(根據實際安裝路徑) #註釋這句斷言: #if version < (1, 3, 3): #raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)
利用Django的ORM鏈接數據庫進行增刪改查和其餘一些進階操做。
一、增:
# 第一種方式 models.UserInfo.objects.create(username='root', password='123') # 第二種方式 dic = {'username': 'root1', 'password': '456'} models.UserInfo.objects.create(**dic) #第三種方式 obj = models.UserInfo(username='root2', password='789') obj.save()
二、刪:
models.UserInfo.objects.filter(id="2").delete()
三、改:
models.UserInfo.objects.filter(id=1).update(password="111")
四、查:
models.User.objects.filter(id=1) #id=1 models.User.objects.filter(id=1,name='root') #id=1 and name = root models.User.objects.filter(id__gt=1) #id>1 models.User.objects.filter(id__lt=1) #id<1 models.User.objects.filter(id__gte=1) #id>=1 models.User.objects.filter(id__lte=1) #id<=1
models.Tb1.objects.filter(id__lt=10, id__gt=1) #1<id<10 dic = {'name': 'xx', 'age__gt': 19} #**字典形式多條件查詢 models.User.objects.filter(**dic) models.Business.objects.all() #QuerySet ,內部元素都是對象 [obj(id,caption,code),obj(id,caption,code),obj(id,caption,code) ] models.Business.objects.all().values('id','caption') # QuerySet ,內部元素都是字典 [{'id':1,'code': 'QA'},{'id':2,'code': 'PM'},...] models.Business.objects.all().values_list('id','caption') # QuerySet ,內部元素都是元組 [(1,"QA"),(2,"PM")] models.Business.objects.get(id=1) # 獲取到的一個對象,若是不存在就報錯 models.Business.objects.filter(id=1).first() # 獲取到的一個對象,若是不存在返回NONE
五、更多進階操做:
1 # 獲取個數 2 # 3 # models.Tb1.objects.filter(name='seven').count() 4 5 # in 6 # 7 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 8 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 9 10 # isnull 11 # Entry.objects.filter(pub_date__isnull=True) 12 13 # contains 14 # 15 # models.Tb1.objects.filter(name__contains="ven") 16 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 17 # models.Tb1.objects.exclude(name__icontains="ven") 18 19 # range 20 # 21 # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and 22 23 # 其餘相似 24 # 25 # startswith,istartswith, endswith, iendswith, 26 27 # order by 28 # 29 # models.Tb1.objects.filter(name='seven').order_by('id') # asc 30 # models.Tb1.objects.filter(name='seven').order_by('-id') # desc 31 32 # group by 33 # 34 # from django.db.models import Count, Min, Max, Sum 35 # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) 36 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 37 38 # limit 、offset 39 # 40 # models.Tb1.objects.all()[10:20] 41 42 # regex正則匹配,iregex 不區分大小寫 43 # 44 # Entry.objects.get(title__regex=r'^(An?|The) +') 45 # Entry.objects.get(title__iregex=r'^(an?|the) +') 46 47 # date 48 # 49 # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) 50 # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) 51 52 # year 53 # 54 # Entry.objects.filter(pub_date__year=2005) 55 # Entry.objects.filter(pub_date__year__gte=2005) 56 57 # month 58 # 59 # Entry.objects.filter(pub_date__month=12) 60 # Entry.objects.filter(pub_date__month__gte=6) 61 62 # day 63 # 64 # Entry.objects.filter(pub_date__day=3) 65 # Entry.objects.filter(pub_date__day__gte=3) 66 67 # week_day 68 # 69 # Entry.objects.filter(pub_date__week_day=2) 70 # Entry.objects.filter(pub_date__week_day__gte=2) 71 72 # hour 73 # 74 # Event.objects.filter(timestamp__hour=23) 75 # Event.objects.filter(time__hour=5) 76 # Event.objects.filter(timestamp__hour__gte=12) 77 78 # minute 79 # 80 # Event.objects.filter(timestamp__minute=29) 81 # Event.objects.filter(time__minute=46) 82 # Event.objects.filter(timestamp__minute__gte=29) 83 84 # second 85 # 86 # Event.objects.filter(timestamp__second=31) 87 # Event.objects.filter(time__second=2) 88 # Event.objects.filter(timestamp__second__gte=31)
注:all()、all().values()、all().values_list()示例:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <h1>業務線列表(對象)</h1> 9 <ul> 10 {% for row in v1 %} 11 <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li> 12 {% endfor %} 13 </ul> 14 <h1>業務線列表(字典)</h1> 15 <ul> 16 {% for row in v2 %} 17 <li>{{ row.id }} - {{ row.code }}</li> 18 {% endfor %} 19 </ul> 20 <h1>業務線列表(元組)</h1> 21 <ul> 22 {% for row in v3 %} 23 <li>{{ row.0 }} - {{ row.1 }}</li> 24 {% endfor %} 25 </ul> 26 </body> 27 </html>
1 from django.shortcuts import render 2 from app1 import models 3 4 5 6 def business(request): 7 v1 = models.Business.objects.all() 8 # QuerySet [obj(id,caption,code),obj(id,caption,code),obj(id,caption,code) ] 9 10 v2 = models.Business.objects.all().values("id", "code") 11 # QuerySet [{'id':1,'code': 'QA'},{'id':2,'code': 'PM'},...] 12 13 v3 = models.Business.objects.all().values_list('id', 'code') 14 # QuerySet [(1,"QA"),(2,"PM")] 15 return render(request, 'business.html', {'v1': v1, 'v2': v2, 'v3': v3})
簡單模擬用戶登錄跳轉後臺,實現編輯用戶、新增用戶、刪除用戶、查看用戶詳情等功能小示例
一、templates:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="/app2/login/" method="POST" enctype="multipart/form-data"> 9 <p> 10 <input type="text" name="user" placeholder="用戶名" /> 11 </p> 12 <p> 13 <input type="password" name="pwd" placeholder="密碼" /> 14 </p> 15 <input type="submit" value="提交"/> 16 </form> 17 </body> 18 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body { 8 margin: 0; 9 } 10 11 .menu { 12 display: block; 13 padding: 5px; 14 15 } 16 </style> 17 </head> 18 <body> 19 <div style="height: 48px;background-color: antiquewhite;color: burlywood"> 20 oms後臺 21 </div> 22 <div> 23 <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;"> 24 <a class="menu" href="/app2/user_info/">用戶管理</a> 25 <a class="menu" href="/app2/user_group/">用戶組管理</a> 26 </div> 27 <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> 28 <h3>添加用戶</h3> 29 30 <form method="POST" action="/app2/user_info/"> 31 <input type="text" name="user"/> 32 <input type="text" name="pwd"/> 33 <input type="submit" value="添加"/> 34 </form> 35 36 <h3>用戶列表</h3> 37 <ul> 38 {% for row in user_list %} 39 <li> 40 <a href="/app2/userDetail-{{ row.id }}">{{ row.username }}</a> | 41 <a href="/app2/userDel-{{ row.id }}">刪除</a> | 42 <a href="/app2/userEdit-{{ row.id }}">編輯</a> 43 </li> 44 {% endfor %} 45 </ul> 46 </div> 47 48 </div> 49 50 </body> 51 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body{ 8 margin: 0; 9 } 10 .menu{ 11 display: block; 12 padding: 5px; 13 14 } 15 </style> 16 </head> 17 <body> 18 <div style="height: 48px;background-color: antiquewhite;color: burlywood"> 19 oms後臺 20 </div> 21 <div> 22 <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;"> 23 <a class="menu" href="/app2/user_info/">用戶管理</a> 24 <a class="menu" href="/app2/user_group/">用戶組管理</a> 25 </div> 26 <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> 27 <h1>編輯用戶</h1> 28 <form method="post" action="/app2/userEdit-{{ obj.id }}/"> 29 <input style="display: none" type="text" name="id" value="{{ obj.id }}" /> 30 <input type="text" name="username" value="{{ obj.username }}" /> 31 <input type="text" name="password" value="{{ obj.password }}"/> 32 <input type="submit" value="提交" /> 33 </form> 34 </div> 35 36 </div> 37 38 </body> 39 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body{ 8 margin: 0; 9 } 10 .menu{ 11 display: block; 12 padding: 5px; 13 14 } 15 </style> 16 </head> 17 <body> 18 <div style="height: 48px;background-color: antiquewhite;color: burlywood"> 19 oms後臺 20 </div> 21 <div> 22 <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;"> 23 <a class="menu" href="/app2/user_info/">用戶管理</a> 24 <a class="menu" href="/app2/user_group/">用戶組管理</a> 25 </div> 26 <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> 27 <h1>用戶詳細信息</h1> 28 <h5>id:{{ obj.id }}</h5> 29 <h5>name:{{ obj.username}}</h5> 30 <h5>password:{{ obj.password }}</h5> 31 </div> 32 33 </div> 34 35 </body> 36 </html>
二、app中的models.py:
1 from django.db import models 2 # Create your models here. 3 4 5 class UserInfo(models.Model): 6 # id列,Django框架會默認生成id(自增,主鍵),也能夠經過AutoField類型自定義主鍵,不過Django框架默認生成ID列會失效 7 # 用戶名列,字符串類型,最大長度長度 8 username = models.CharField(max_length=32) 9 password = models.CharField(max_length=64)
二、app中的urls.py:
from django.conf.urls import url from app2 import views urlpatterns = [ url(r'^orm', views.orm_action), url(r'^login', views.login), url(r'^oms', views.oms), url(r'^user_info', views.user_info), url(r'^userDetail-(?P<nid>\d+)', views.user_detail), url(r'^userDel-(?P<nid>\d+)', views.user_del), url(r'^userEdit-(?P<nid>\d+)', views.user_edit), ]
三、app中的views.py:
1 from django.shortcuts import render 2 from django.shortcuts import redirect 3 from app2 import models 4 5 6 # 登陸 7 def login(request): 8 if request.method == "GET": 9 return render(request, 'login.html') 10 elif request.method == "POST": 11 u = request.POST.get('user') 12 p = request.POST.get('pwd') 13 # 兩種方式判斷數據庫中是否有匹配的數據 14 # obj = models.UserInfo.objects.filter(username=u,password=p).first() # 推薦這一種 15 # count = models.UserInfo.objects.filter(username=u, password=p).count() 16 obj = models.UserInfo.objects.filter(username=u, password=p).first() 17 if obj: 18 return redirect('/app2/user_info') 19 else: 20 return render(request, 'login.html') 21 else: 22 # PUT,DELETE,HEAD,OPTION... 23 return redirect('/login') 24 25 26 # 後臺頁面 27 def user_info(request): 28 if request.method == "GET": 29 user_list = models.UserInfo.objects.all() 30 print(user_list.query) # .query 查看原生sql語句 31 return render(request, "user_info.html", {"user_list": user_list}) 32 elif request.method == "POST": 33 u = request.POST.get("user") 34 p = request.POST.get("pwd") 35 models.UserInfo.objects.create(username=u, password=p) 36 # 添加用戶後返回添加頁面查看新增數據 37 # 方式一 38 # user_list = models.UserInfo.objects.all() 39 # return render(request, "user_info.html", {"user_list": user_list}) 40 # 方式二 有效避免重複代碼 41 return redirect("/app2/user_info") 42 43 44 # 查看用戶詳情 45 def user_detail(request, nid): 46 # 取單條數據的兩種方式 47 # 第一種(推薦) 48 obj = models.UserInfo.objects.filter(id=nid).first() 49 # 第二種(當數據爲空,直接報錯) 50 # models.UserInfo.objects.get(id=nid) 51 return render(request, "user_detail.html", {"obj": obj}) 52 53 54 # 刪除用戶 55 def user_del(request, nid): 56 models.UserInfo.objects.filter(id=nid).delete() 57 return redirect("/app2/user_info") 58 59 60 # 編輯用戶 61 def user_edit(request, nid): 62 if request.method == "GET": 63 obj = models.UserInfo.objects.filter(id=nid).first() 64 return render(request, "user_edit.html", {"obj": obj}) 65 elif request.method == "POST": 66 user_id = request.POST.get('id') 67 u = request.POST.get('username') 68 p = request.POST.get('password') 69 models.UserInfo.objects.filter(id=user_id).update(username=u, password=p) 70 return redirect("/app2/user_info")
一、支持鏈式查詢QuerySet方法:
1 def all(self) 2 # 獲取全部的數據對象 3 4 def filter(self, *args, **kwargs) 5 # 條件查詢 6 # 條件能夠是:參數,字典,Q 7 8 def exclude(self, *args, **kwargs) 9 # 條件查詢 10 # 條件能夠是:參數,字典,Q 11 12 def annotate(self, *args, **kwargs) 13 # 用於實現聚合group by查詢 14 15 from django.db.models import Count, Avg, Max, Min, Sum 16 17 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')) 18 # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id 19 20 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1) # 支持having子句,放在最開始的地方就是where子句,放在這邊就是having子句 21 # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 22 23 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1) # distinct=True去重 24 # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 25 26 def distinct(self, *field_names) 27 # 用於distinct去重 28 models.UserInfo.objects.values('nid').distinct() 29 # select distinct nid from userinfo 30 31 注:只有在PostgreSQL中才能使用distinct進行去重,不支持mysql數據庫 32 33 def order_by(self, *field_names) 34 # 用於排序 35 models.UserInfo.objects.all().order_by('-id','age') 36 37 def reverse(self): 38 # 倒序 39 models.UserInfo.objects.all().order_by('-nid').reverse() 40 # 這個須要跟order_by配合使用,若是不存在order_by,則沒有任何效果 41 # 若是存在order_by,reverse則是倒序,若是多個排序則一一倒序 42 43 def defer(self, *fields): 44 #查詢表中的數據,排除username、id列數據,將剩餘列數據組合成querySet對象進行返回 45 models.UserInfo.objects.defer('username','') 46 models.UserInfo.objects.filter(...).defer('username','id') 47 48 def only(self, *fields): 49 #查詢表中的數據,僅取username、id列中的數據組合成querySet對象進行返回,與defer相反 50 models.UserInfo.objects.only('username','id') 51 models.UserInfo.objects.filter(...).only('username','id') 52 53 def using(self, alias): 54 models.Blog.objects.filter(name="root").filter("id=1").all().using(alias="default1") #這個看你settings裏面的設置 55 #指定使用的數據庫進行操做(從settings中讀取DATABASES配置),使用場景:好比數據庫的讀寫分離,讀的是A庫,寫的是B庫 56 57 58 # 在原生的sql語句中會遇到一些複雜的sql,如msyql自定義的函數和過程、額外的查詢條件、映射、子查詢 59 def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) #tables可不傳,實例化的時候已傳表名,order_by看使用場景使用 60 61 ## select與select_params配合,以%s進行傳參,參數能夠是元組,是可迭代的序列便可 62 Entry.objects.extra(select={'new_id': "%s"}, select_params=(1,))#select的參數,%s 就會替換成 1 63 #select *,1 as cid from Entry 64 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) 65 #select *,(select col from sometable where nid = 1) as new_id from Entry 66 Entry.objects.extra(select={'new_id': "func(1)"}) #能夠直接放函數 67 #select func(1) as new_id 68 69 70 ##where與params配合,加額外的where條件語句,以%s進行傳參,參數能夠是元組,是可迭代的序列便可 71 Entry.objects.extra(where=["name='a' OR age = 22"]) # or 72 Entry.objects.extra(where=["age = 22", "name='a'"]) # and 73 Entry.objects.extra(where=["func(arg)=2000"], params=['5']) 74 Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 75 76 77 #性能相關的內置方法 78 def select_related(self, *fields) 79 #一、 80 users = User.objects.all() 81 for row in users: 82 #僅僅是用戶表的數據不會再去請求數據庫,user_type表須要再次發送請求,可是若是這邊10條用戶表的數據有十條,總共就會請求10+1次數據庫 83 print(row.name,row.sex) 84 print(row.ut.type_name) #再次請求一次數據庫 85 86 #二、 87 users = User.objects.all().values("name","sex","ut__type_name") #若是是這種的話,就會只請求一次數據庫,但數據不是querySet對象類型 88 89 #三、 90 #只拿ut對應的user_type表一次性拿過來 91 users = User.objects.all().select_related("ut") #只關聯ut這張表,取出來,其餘的表都不關聯,由於一張表裏面能夠有多個外鍵 92 for row in users: 93 print(row.name,row.sex) 94 print(row.ut.type_name) 95 print(row.tu.name) #tu沒有加進去,因此這邊會再次django發送數據庫請求 96 97 98 99 def prefetch_related(self, *lookups) 100 #通常在生產環境,不多連表查詢,由於這樣效率很低,咱們通常都是空間換時間,因此這個就會用到prefetch_related,用到這個,會作屢次查詢,保證每次都是單表查詢 101 users = User.objects.filter(ut_id__gt=30).prefetch_related('ut') #這邊也能夠多加幾個外鍵 102 #解析步驟 103 ## select * from users where id > 30 固然這邊不會用*的,通常會把全部字段都打印出來,效率更高 104 ## 獲取上一步中全部ut_id = [1,2]的數據 105 ## select * from user_type where id in [1,2] 106 #這邊django已經經過以上步驟,把要查詢的數據放到內存中,全部就不用向數據庫發送請求了,就能夠直接從內存中獲取 107 for row in users: 108 print(row.name,row.sex) 109 print(row.ut.type_name)
二、不支持鏈式查詢QuerySet方法:
1 def raw(self, raw_query, params=None, translations=None, using=None): 2 # 執行原生SQL 3 models.UserInfo.objects.raw('select * from userinfo') 4 #obj = User.objects.raw('select id,name,password from tb ') 5 6 # 若是SQL是其餘表時,必須將名字設置爲當前UserInfo對象的主鍵列名, 7 models.UserInfo.objects.raw('select id as nid from 其餘表') 8 #能夠下面的方式將tb2裏面的數據複製在tb中 9 #obj = User.objects.raw('select nid as id,username as name,email as password from tb2 ') 10 11 # 爲原生SQL設置參數 12 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) 13 14 # 將獲取的到列名轉換爲指定列名 15 name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} 16 Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) 17 18 # 指定數據庫 19 models.UserInfo.objects.raw('select * from userinfo', using="default") 20 21 ################### 原生SQL ################### 22 from django.db import connection, connections 23 cursor = connection.cursor() # cursor = connections['default'].cursor() 24 cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 25 row = cursor.fetchone() # fetchall()/fetchmany(..) 26 27 28 def values(self, *fields): 29 # 獲取每行數據爲字典格式 30 31 def values_list(self, *fields, **kwargs): 32 # 獲取每行數據爲元祖 33 34 def dates(self, field_name, kind, order='ASC'): 35 # 根據數據庫中時間列名進行某一部分進行去重查找並截取指定內容 36 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) 37 # order只能是:"ASC" "DESC" 38 # 並獲取轉換後的時間 39 - year : 年-01-01 40 - month: 年-月-01 41 - day : 年-月-日 42 43 models.DatePlus.objects.dates('ctime','day','DESC') 44 45 def datetimes(self, field_name, kind, order='ASC', tzinfo=None): 46 # 根據數據庫中時間列名進行某一部分進行去重查找並截取指定內容,將時間轉換爲指定時區時間 47 # kind只能是 "year", "month", "day", "hour", "minute", "second" 48 # order只能是:"ASC" "DESC" 49 # tzinfo時區對象 50 #指定時區須要下載pytz庫 51 """ 52 pip3 install pytz 53 import pytz 54 pytz.all_timezones 55 pytz.timezone(‘Asia/Shanghai’) 56 """ 57 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC) 58 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) 59 60 61 62 def none(self): 63 # 返回一個空QuerySet對象
三、數據庫操做:
如:批量插入數據庫,對整個數據作聚合操做
1 def aggregate(self, *args, **kwargs): 2 # 聚合函數,獲取字典類型聚合結果 3 from django.db.models import Count, Avg, Max, Min, Sum 4 result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid')) # distinct=True 先去重,再執行聚合 至關於sql以下: #select count(nid) as n from user 5 6 def count(self): 7 # 獲取個數 8 9 def get(self, *args, **kwargs): 10 # 獲取單個對象 11 12 def create(self, **kwargs): 13 # 建立對象 14 15 def bulk_create(self, objs, batch_size=None): 16 # 批量插入 17 # batch_size表示一次插入的個數 18 objs = [ 19 models.DDD(name='r11'), 20 models.DDD(name='r22') 21 ] 22 models.DDD.objects.bulk_create(objs, 10) 23 24 def get_or_create(self, defaults=None, **kwargs): 25 # 若是存在,則獲取,不然,建立 26 # defaults 指定建立時,其餘字段的值 27 obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) 28 29 def update_or_create(self, defaults=None, **kwargs): 30 # 若是存在,則更新,不然,建立 31 # defaults 指定建立時或更新時的其餘字段 32 obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) 33 34 def first(self): 35 # 獲取第一個 36 37 def last(self): 38 # 獲取最後一個 39 40 def in_bulk(self, id_list=None): 41 # 根據主鍵ID進行查找 42 id_list = [11,21,31] 43 models.DDD.objects.in_bulk(id_list) #至關於in操做 44 45 def delete(self): 46 # 刪除 47 48 def update(self, **kwargs): 49 # 更新 50 51 def exists(self): 52 # 是否有結果 53 54 METHODS THAT DO DATABASE QUERIES
四、QuerySet序列化:
1 #第一種 2 ##使用Django內置的方法對queryset類型的數據進行序列化 3 4 from django.core import serializers 5 ret = models.BookType.objects.all() 6 data = serializers.serialize("json", ret) 7 8 9 #第二種 10 ##使用json.dumps對queryset類型的數據進行序列化 11 ####當list中queryset類型中沒有複雜的數據類型(如:時間類型)能夠直接使用json.dumps 12 import json 13 #ret = models.BookType.objects.all().values('caption') 14 ret = models.BookType.objects.all().values_list('id','caption') 15 ret=list(ret) 16 result = json.dumps(ret) 17 18 ####當list中queryset類型中沒有複雜的數據類型(如:時間)能夠直接使用json.dumps 19 import json 20 from datetime import date 21 from datetime import datetime 22 23 #自定義encoder 24 class JsonCustomEncoder(json.JSONEncoder): 25 26 def default(self, field): 27 28 if isinstance(field, datetime.datetime): 29 return field.strftime('%Y-%m-%d %H:%M:%S') 30 elif isinstance(field, date): 31 return field.strftime('%Y-%m-%d') 32 else: 33 return json.JSONEncoder.default(self, field) 34 35 #再序列化帶有相似於ctime複雜的數據類型 36 ret = models.BookType.objects.all().values_list('caption','ctime') 37 38 ret=list(ret) 39 40 result = json.dumps(ret, cls=JsonCustomEncoder)
django Model也是支持數據驗證的,只是這個數據驗證比較弱而已,只能支持單個的驗證,可是對於組合的、固定的,就沒法進行相關數據驗證了
一、models.py
class User(models.Model): name = models.CharField(max_length=32,db_index=True) #建立索引 email = models.EmailField(max_length=30) #Model經過clean()函數設置鉤子 def clean(self): #Model內部對全部字段進行正則驗證,完畢以後纔會執行這個clean方法 from django.core.exceptions import ValidationError c = User.objects.filter(name=self.name).count() if c: raise ValidationError
二、views.py
from app01 import models def index(request): obj = models.User(name="root",email="root") obj.full_clean() #沒有這個,name是不作驗證的,有了full_clean是須要作驗證的,驗證不經過是要報錯的,因此驗證的時候,咱們直接本身抓異常,進行異常處理 obj.save() return HttpResponse("hello")