ORM:object relational mapping,對象關系映射
django中使用原生sql的弊端:
1、SQL語句重復率很高,利用率不高
2、如果業務邏輯生變,原生SQL更改起來比較多
3、容易忽略一些web安全問題,如SQL注入
ORM的優點:
易用性:使用ORM做數據庫的開發可以有效的減少重復SQL語句的概率,寫出來的模型也更加直觀、清晰。
性能損耗小:ORM轉換成底層數據庫操作指令確實會有一些開銷。但從實際的情況來看,這種性能損耗很少(不足5%),只要不是對性能有嚴苛的要求,綜合考慮開發效率、代碼的閱讀性,帶來的好處要遠遠大於性能損耗,而且項目越大作用越明顯。
設計靈活:可以輕松的寫出復雜的查詢。
可移植性:Django封裝了底層的數據庫實現,支持多個關系數據庫引擎,包括流行的MySQL、PostgreSQL和SQLite。可以非常輕松的切換數據庫。
ORM常用字段類型:
1、CharField:字符串類型,映射到數據庫中會轉換成varchar類型,使用時必須傳入max_length屬性以定義該字符串的最大長度,如果超過254個字符,就不建議使用CharField了,此時建議使用TextField。
2、EmailField:在數據庫底層也是一個varchar類型,默認最大長度是254個字符,當然也可以自己傳遞max_length參數,這個Field在數據庫層面不會限制一定要傳遞符合email條件的字符串,只是以后在使用ModelForm表單驗證時,會起作用
3、URLField:類似於CharField,在數據庫底層也是一個varchar類型,只不過只能用來存儲url格式的字符串。並且默認的max_length是200,同EmailField
4、FloatField:浮點數類型,映射到數據庫中會變成double類型
5、IntegerField:整數類型,映射到數據庫中會變成11位的int類型
6、BigIntegerField:大整形。值的區間是-9223372036854775808——9223372036854775807
7、PositiveIntegerField:正整形。值的區間是0——2147483647
8、SmallIntegerField:小整形。值的區間是-32768——32767
9、PositiveSmallIntegerField:正小整形。值的區間是0——32767
10、BooleanField:布爾類型(True/False),映射到數據庫中會變成長度只有1位的tinyint類型,這個Field不接受null參數,要想使用可以為null的布爾類型的字段,就要使用NullBooleanField
11、AutoField:自增長類型,映射到數據庫中是11位的整數,使用此字段時,必須傳遞primary_key=True,否則在生成遷移腳本文件時,就會報錯,一個模型不能有兩個自增長字段。一般情況下我們用不到這個字段,如果不定義主鍵,django會自動的為我們生成id字段作為主鍵
12、BigAutoField:自增長類型,用法同AutoField。映射到數據庫中會成為20位的bigint類型
13、DateTimeField:日期時間類型,在python中對應的是datetime.datetime類型,在映射到數據庫中也是datetime類型。使用這個Field可以傳遞以下幾個參數:
auto_now=True:在每次這個數據保存的時候,都使用當前的時間。比如作為一個記錄修改日期的字段
auto_now_add=True:在每條數據第一次被添加進去的時候,都使用當前的時間。比如作為一個記錄第一次入庫的字段
注意:如果在setting.py中配置了USE_TZ=True,那么上兩個默認值都來自於django.utils.timezone.now所轉化來的值
在模板中將一個UTC時間轉換成本地時間:
首先模板HTML文件的開頭導入tz:
{% load tz %}
在傳遞過來的時間變量utc_time中使用localtime過濾器:
{{utc_time | localtime}}
其實,django知道我們的想法,已經為我們做好了配置,我們並不需要配置其他的東西就可以直接使用{{utc_time}},此時只要我們在setting.py文件中設置 USE_TZ=True,TIME_ZONE='Asia/Shanghai',UTC時間變量在渲染到模板上的時候會自動的為我們加載成TIME_ZONE中所設置的時區的時間。
14、DateField:日期類型,用法同DateTimeField,在python中對應的是datetime.date類型,在映射到數據庫中是date類型
15、TimeField:時間類型,用法同DateTimeField,在python中對應的是datetime.time類型,在映射到數據庫中是time類型
16、FileField:用來存儲文件的
17、ImageField:用來存儲圖片文件的
18、TextField:大量的文本類型
19、DecimalField: 一個固定精度的十進制數類型,使用時必須要傳遞兩個參數,max_digits數字的最大總長度(不含小數點),decimal_places小數部分的長度
Field的常用參數:
1、null:標識是否可以為空,默認是為False。在使用字符串相關的Field(CharField/TextField/URLField/EmailField)的時候,官方推薦盡量不要使用這個參數,也就是保持默認值False。因為Django在處理字符串相關的Field的時候,即使這個Field的null=False,如果你沒有給這個Field傳遞任何值,那么Django也會使用一個空的字符串""來作為默認值存儲進去。因此如果再使用null=True,Django會產生兩種空值的情形(NULL或者空字符串)。如果想要在表單驗證的時候允許這個字符串為空,那么建議使用blank=True。如果你的Field是BooleanField,由於BooleanField不接受null參數,因此你如果想要設置這個字段可以為空的bool類型,那么對應的可空的bool類型字段則為NullBooleanField。
2、blank:標識這個字段在表單驗證的時候是否可以為空,默認是False。這個和null是有區別的,null是一個純數據庫級別的。而blank是表單驗證級別的。
3、db_column:這個字段在數據庫中的名字。如果沒有設置這個參數,那么將會使用模型中屬性的名字。
4、db_index:標識這個字段是否為索引字段。
5、default:默認值。可以為一個值,或者是一個函數,但是不支持lambda表達式。並且不支持列表/字典/集合等可變的數據結構。在用函數作為值傳遞給default時,只能傳遞函數名,不需要加括號。
6、primary_key:是否為主鍵,與AutoField/BigAutoField連用,默認是False。
7、unique:在表中這個字段的值是否唯一,在數據庫中就是唯一約束,一般是設置手機號碼/郵箱等。
8、choices:在一個范圍內選擇出一項,注意這個選項與ForeignKey的區別
作用:1、django admin中顯示下拉框;2、避免連表查詢
TYPE_CHOICES = ( #數據庫只保存內部元祖的第一個值,后面的值保存在內存中
(0, '---'),
(1, '第一類'),
(2, '第二類'),
(3, '第三類'),
)
type = models.IntegerField(default=0,choices=TYPE_CHOICES)
模型中Meta配置:
對於一些模型級別的配置。我們可以在模型中定義一個類,叫做Meta。然后在這個類中添加一些類屬性來控制模型的作用。比如我們想要在數據庫映射的時候使用自己指定的表名,而不是使用模型的名稱。那么我們可以在Meta類中添加一個db_table的屬性。示例代碼如下:
class Book(models.Model):
name = models.CharField(max_length=20,null=False)
desc = models.CharField(max_length=100,null=True,blank=True)
class Meta:
db_table = 'book_model'
以下將對Meta類中的一些常用配置進行解釋。
1、db_table:這個模型映射到數據庫中的表名。如果沒有指定這個參數,那么在映射的時候將會使用模型所在app的名稱加上模型名的小寫來作為默認的表名。
2、ordering:設置在提取數據的排序方式,因為可以按照多個字段以優先關系進行排序,所以需要傳遞一個字段的列表,在我們提取數據時,可以根據列表中字段從前到后(優先級從高到低)的方式排序,排序默認為正序,如果你需要哪個字段按倒序排列,就可以在這個字段前面加上"-"。后面章節會講到如何查找數據。比如我想在查找數據的時候根據添加的時間排序,那么示例代碼如下:
class Book(models.Model):
name = models.CharField(max_length=20,null=False)
desc = models.CharField(max_length=100,name='description',db_column="description1")
pub_date = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'book_model'
ordering = ['pub_date',]