到目前爲止,當程序涉及到數據庫相關操做時,咱們通常都會這麼操做:
(1)建立數據庫,設計表結構和字段
(2)使用MySQLdb來鏈接數據庫,並編寫數據訪問層代碼
(3)業務邏輯層去調用數據訪問層,執行數據庫操做html
import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='mydb', passwd='123', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchall() db.close() return data def GetSingle(sql): db = MySQLdb.connect(user='root', db='mydb', passwd='123', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return data
Django爲使用一種新的方式,即:關係對象映射(Object Relational Mapping,簡稱ORM)。Django遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。Django是經過Model類來操做數據庫的,程序員不須要關注SQL語句和數據庫的類型(不管數據庫是MySql、Sqlite,仍是其它類型),Django自動生成相應數據庫類型的SQL語句,來完成對數據庫數據的操做。python
當咱們在已經建立的Django工程中建立app時(假設app的名稱爲app01),那麼在app01模塊下默認會生成models.py文件,這個就是Django工程中操做數據庫的文件。 git
1 建立數據庫Model類(models.py文件)程序員
#/usr/bin/env python #-*- coding:utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. # ORM模型 # 類 -> 數據庫表 # 對象 -> 表中的每一行數據 # 對象.id,對象.value -> 每行中的數據 #這個類是用來生成數據庫表的,這個類必須繼承models.Model類 class UserInfo(models.Model): #建立表的字段 username = models.CharField(max_length=16) #建立一個字段,類型爲字符串類型,最大長度爲16 password = models.CharField(max_length=32) #建立一個字段,類型爲字符串類型,最大長度爲32 #注:對於ORM框架,能夠簡單的認爲自定義類UserInfo表示數據庫的表;根據UserInfo建立的對象表示數據庫表 #裏的一行數據;而對象.username和對象.password表示每一行數據裏具體的字段(username/password)的數據。
(1)更多字段類型
正則表達式
通常數據庫中字段類型大概5種(字符串/數字/浮點型/時間類型/布爾類型),但Django爲了在後臺admin中能夠操做數據庫,同時爲了限制在admin中對數據庫的無效操做,Model中設置了不少種數據類型。 sql
一、models.AutoField 自增列=int(11) 若是沒有的話,默認會生成一個名稱爲id的列,若是要顯示的定義一個自增列,必須把該列設置爲主鍵(primary_key=True) 二、models.CharField 字符串類型字段 必須加max_length參數 三、models.BooleanField 布爾類型字段=tinyint(1) 不能爲空,Blank=True 四、models.ComaSeparatedIntegerField 用逗號分割的數字類型=varchar 繼承CharField,因此必須加max_lenght參數 五、models.DateField 日期字段類型date 參數auto_now=True表示每次更新都會更新這個時間;參數auto_now_add表示只是第一次建立時添加,以後的更新再也不改變 六、models.DateTimeField 日期字段類型datetime 同DateField的參數 七、models.Decimal 十進制小數類型=decimal 必須指定整數位max_digits和小數位decimal_places 八、models.EmailField 字符串類型(正則表達式郵箱)=varchar 對字符串進行正則表達式驗證 九、models.FloatField 浮點類型=double 十、models.IntegerField 整形 十一、models.BigIntegerField 長整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 十二、models.IPAddressField 字符串類型(ip4正則表達式) 1三、models.GenericIPAddressField 字符串類型(ip4和ip6是可選的) 參數protocol能夠是:both、ipv四、ipv6 驗證時,會根據設置進行報錯 1四、models.NullBooleanField 容許爲空的布爾類型 1五、models.PositiveIntegerFiel 正Integer 1六、models.PositiveSmallIntegerField 正smallInteger 1七、models.SlugField 減號、下劃線、字母、數字 1八、models.SmallIntegerField 數字 數據庫中的字段有:tinyint、smallint、int、bigint 1九、models.TextField 字符串=longtext 20、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 2一、models.URLField 字符串類型,地址正則表達式 2二、models.BinaryField 二進制 2三、models.ImageField 圖片 2四、models.FilePathField 文件 |
models.DateTimeField/models.GenericIPAddressField/models.ImageField使用字段說明數據庫
class UserInfo(models.Model): name = models.CharField(max_length=32) ctime = models.DateTimeField(auto_now=True) #每當你建立一行數據時,Django就會在該行數據中增長一個ctime字段 uptime = models.DateTimeField(auto_now_add=True) #當前表任何一行數據有更新時,Django就會自動更新該字段. #下面兩項是新增的字段,注意新增時參數的設置,不然在命令行建立數據庫時報錯,null=True表示在數據庫中該字段能夠爲空,default='xxx'表示默認值
email_1 = models.EmailField(max_length=32,null=True) email_2 = models.EmailField(max_length=32,default='aaa@qq.com') #新增字段,blank=True表示admin後臺能夠爲空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True)
#upload_to='upload'表示用戶上傳數據存儲的位置,這裏須要注意:在數據庫中實際保存的並非文件,而是文件存放的路徑 img = models.ImageField(null=True,blank=True,upload_to='upload')
(2)更多參數類型django
一、null=True 數據庫中字段是否能夠爲空 二、blank=True django的Admin中添加數據時是否可容許空值 三、primary_key=False 主鍵,對AutoField設置主鍵後,就會代替原來默認的自增id列 四、auto_now和auto_now_add auto_now 自動建立---不管添加或修改,都是當前操做的時間 auto_now_add 自動建立---永遠是建立時的時間 五、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices=GENDER_CHOICE) 六、max_length 最大長度 七、default 默認值 八、verbose_name Admin中字段的顯示名稱 九、name|db_column 數據庫中的字段名稱 十、unique=True 不容許重複 十一、db_index = True 數據庫索引 十二、editable=True 在Admin裏是否可編輯 1三、error_messages=None 錯誤提示 1四、auto_created=False 自動建立 1五、help_text 在Admin中提示幫助信息 1六、validators=[] 驗證 1七、upload-to 文件上傳路徑 |
(3)Model類的擴展編程
輸出Model對象默認返回值json
class UserInfo(models.Model): name = models.CharField(max_length=32) ctime = models.DateTimeField(auto_now=True) #每當你建立一行數據時,Django就會在該行數據中增長一個ctime字段
uptime = models.DateTimeField(auto_now_add=True) #當前表任何一行數據有更新時,Django就會自動更新該字段.
#下面兩項是新增的字段,注意新增時參數的設置,不然在命令行建立數據庫時報錯,null=True表示在數據庫中該字段能夠爲空,default='xxx'表示默認值
email_1 = models.EmailField(max_length=32,null=True) email_2 = models.EmailField(max_length=32,default='aaa@qq.com') #新增字段,blank=True表示admin後臺能夠爲空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True) #upload_to='upload'表示用戶上傳數據存儲的位置,這裏須要注意:在數據庫中實際保存的並非文件,而是文件存放的路徑
img = models.ImageField(null=True,blank=True,upload_to='upload')
#下面的__unicode__(self)方法,表示當輸出這個類建立的對象時,默認會輸出這個對象的name字段 def __unicode__(self): return self.name
def model(request): #建立兩條數據
models.UserInfo.objects.create(name='alex') models.UserInfo.objects.create(name='eric') obj_1 = models.UserInfo.objects.all() obj_2 = models.UserInfo.objects.filter(name='alex') #輸出obj及其類型
print obj_1,type(obj_1) print obj_2,type(obj_2) return HttpResponse('ok')
若是不加上述__unicode__(self)方法,則輸出結果爲
[<UserInfo: UserInfo object>, <UserInfo: UserInfo object>] <class 'django.db.models.query.QuerySet'> [<UserInfo: UserInfo object>,] <class 'django.db.models.query.QuerySet'>
若是加上上述__unicode__(self)方法,則輸出結果爲
[<UserInfo: alex>, <UserInfo: eric>] <class 'django.db.models.query.QuerySet'> [<UserInfo: alex>,] <class 'django.db.models.query.QuerySet'>
在數據庫表已經生成的狀況下,添加新的字段報錯,錯誤信息以下:
localhost:Django_lastday luotim$ python manage.py makemigrations You are trying to add a non-nullable field 'email' to userinfo without a default; we can't do that (the database needs something to
populate existing rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows) 2) Quit, and let me add a default in models.py Select an option:
當你在已有的數據庫表中添加一個非空的字段的時,因爲原表中已有的行沒有這個字段,那麼就會致使報錯。解決辦法就是:容許爲空、或者設置默認值。假設在已有的表中添加以下兩個字段,那麼能夠設置字段爲空,或者給字段設置默認值
email_1 = models.EmailField(max_length=32,null=True) email_2 = models.EmailField(max_length=32,default='aaa@qq.com')
上傳圖片實例
class UserInfo(models.Model): name = models.CharField(max_length=32) ctime = models.DateTimeField(auto_now=True) #每當你建立一行數據時,Django就會在該行數據中增長一個ctime字段
uptime = models.DateTimeField(auto_now_add=True) #當前表任何一行數據有更新時,Django就會自動更新該字段.
#下面兩項是新增的字段,注意新增時參數的設置,不然在命令行建立數據庫時報錯,null=True表示在數據庫中該字段能夠爲空,default='xxx'表示默認值
email_1 = models.EmailField(max_length=32,null=True) email_2 = models.EmailField(max_length=32,default='aaa@qq.com') #新增字段,blank=True表示admin後臺能夠爲空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True) #upload_to='upload'表示用戶上傳數據存儲的位置,這裏須要注意:在數據庫中實際保存的並非文件,而是文件存放的路徑
img = models.ImageField(null=True,blank=True,upload_to='upload') def __unicode__(self): return self.name
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> {#注意form表單提交文件時,form中的enctype="multipart/form-data"參數表示分片上傳#} <form action="/upload/" method="post" enctype="multipart/form-data">
<p><input type="file" name="f1"/></p>
<p><input type="file" name="f2"/></p>
<p><input type="text" name="hostname"/></p>
<input type="submit" value="upload"/>
</form>
</body>
</html>
def upload(request): if request.method == 'POST': # 這裏只會獲取type='text'的內容 inp_post = request.POST # 這裏獲取提交文件的文件名,字典形式 inp_files = request.FILES # 獲取name='f1'對應的文件對象 file_obj1 = inp_files.get('f1') print file_obj1,type(file_obj1) # from django.core.files.uploadedfile import InMemoryUploadedFile # 獲取對應的文件名 print file_obj1.name # 注意在windows下,打開模式爲'wb',不然出錯 f = open(file_obj1.name,'wb') # 分片傳輸,每64k寫一次,chunks方法中利用了yield,生成器 print file_obj1.chunks() for line in file_obj1.chunks(): f.write(line) f.close() return render(request,'home/upload.html')
2 註冊APP(settings.py文件)
# Application definition
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
3 執行命令(Django 1.9)
python manage.py makemigrations
python manage.py migrate
當執行python manage.py makemigrations命令時,在Django工程中會生成如圖所示的文件(其中migrations爲新生成的模塊,紅框中爲新生成的文件)
其中0001_initial.py文件的內容以下(至關於生成一個數據庫源,後面生成數據庫表會按照這個數據庫源來生成)
# -*- coding: utf-8 -*- # Generated by Django 1.9.2 on 2016-03-11 12:46
from __future__ import unicode_literals from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [] operations = [ migrations.CreateModel( name='UserInfo', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('username', models.CharField(max_length=16)), ('password', models.CharField(max_length=32)), ], ), ]
而後執行python manage.py migrate命令,它會讀取0001_initial.py這個數據庫結構文件從而生成數據庫表。
4 經過admin來查看數據庫
先建立超級用戶,而後在admin.py文件中按照以下進行配置
#/usr/bin/env python #-*- coding:utf-8 -*-
from django.contrib import admin # Register your models here.
from app01 import models #註冊models.py文件中建立的類
admin.site.register(models.UserInfo)
而後能夠經過頁面訪問到以下信息
1 基本操做
# 增--3種方法 |
數據庫建立數據實例
#hmtl文件
<form action="/add_user/" method="post">
<p>用戶名:{{ obj.username }}</p>
<p>密碼:{{ obj.password }}</p>
<input type="submit" value="submit"/>
</form>
#forms模塊中的account.py文件
class AddUser(forms.Form): username = forms.CharField() password = forms.CharField(widget=forms.PasswordInput()) #views模塊中的login.py文件
def add_user(request): obj = AccountForm.AddUser(request.POST) if request.method == 'POST': if obj.is_valid(): user_input = obj.clean() print user_input #用戶輸入的就是字典類型,因此參數爲**user_input
models.UserInfo.objects.create(**user_input) print models.UserInfo.objects.all() return render(request,'account/add_user.html',{'obj':obj}) return render(request,'account/add_user.html',{'obj':obj}) #結果
--print user_input {'username': u'xxx', 'password': u'123'} --print models.UserInfo.objects.all() 返回值 [<UserInfo: xxx>, <UserInfo: alex>,] #Model類中添加了__unicode__方法
數據庫查找數據實例
from django import forms from app01 import models class ImportForm(forms.Form): # 優化後的寫法,設置select的數據爲空 admin = forms.IntegerField( widget=forms.Select() ) # 爲了實時的獲取文件中的數據,從新寫了構造方法,這樣當修改了文件數據,從新請求時(不須要重啓) # 實時的獲取文件中的數據,由於每次請求時都會把類實例化,那麼就會執行類的構造方法,這裏利用了 # 面向對象編程的思想(靜態字段屬於類),好好體會這裏面的思想 def __init__(self,*args,**kwargs): super(ImportForm,self).__init__(*args,**kwargs) # 一、從文件中獲取數據,而後賦值給self.fields['admin'].widget.choices # import json # f = open('db_admin') # data = f.read() # data_tuple = json.loads(data) # self.fields是深拷貝的結果self.fields = copy.deepcopy(self.base_fields) # self.fields['admin'].widget.choices = data_tuple # 二、直接從數據庫中獲取self.fields['admin'].widget.choices self.fields['admin'].widget.choices = models.SimpleModel.objects.all().values_list('id','username')
from django.shortcuts import render,HttpResponse from app01.forms import home as HomeForm from app01 import models def index(request): # 建立一行數據 # dic = {'username':'alex','password':'123'} # models.SimpleModel.objects.create(**dic) res = models.SimpleModel.objects.all() #對應的sql語句"SELECT "app01_simplemodel"."id", "app01_simplemodel"."username", "app01_simplemodel"."password" FROM "app01_simplemodel"" print res.query #[<SimpleModel: SimpleModel object>] 列表 print res # <class 'django.db.models.query.QuerySet'> 類 print type(res) # 取某個字段值,字典 ret = models.SimpleModel.objects.all().values('username') # [{'username': u'alex'}] 字典 print ret # <class 'django.db.models.query.QuerySet'> print type(ret) # 取某個字段值,列表 ref1 = models.SimpleModel.objects.all().values_list('username') # [(u'alex',)] 元組組成的列表 print ref1 # <class 'django.db.models.query.QuerySet'> print type(ref1) # [(1, u'alex')] 獲取(id,username)元組組成的列表 ref2 = models.SimpleModel.objects.all().values_list('id','username') print ref2 obj = HomeForm.ImportForm() return render(request,'home/index.html',{'obj':obj})
class SimpleModel(models.Model): username = models.CharField(max_length=64) password = models.CharField(max_length=64)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>錄入數據</h1> <form action="/index/"> <p>{{ obj.host_type }} </p> <p>{{ obj.hostname }}</p> <p>{{ obj.admin }}</p> </form> <h1>數據列表</h1> </body> </html>
值得注意的地方: #獲取指定列的值,能夠傳多個參數,它的結果爲字典形式 |
2 進階操做(了不得的雙下劃線)
利用雙下劃線將字段和對應的操做鏈接起來
# 獲取個數 |
參考資料:
http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html