1、ORM介紹 1、ORM概念 對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種爲了解決面向對象與關係數據庫存在的互不匹配的現象的技術。 簡單的說,ORM是經過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關係數據庫中。 ORM在業務邏輯層和數據庫層之間充當了橋樑的做用。 2、ORM由來 讓咱們從O/R開始。字母O起源於"對象"(Object),而R則來自於"關係"(Relational)。 幾乎全部的軟件開發過程當中都會涉及到對象和關係數據庫。在用戶層面和業務邏輯層面,咱們是面向對象的。當對象的信息發生變化的時候,咱們就須要把對象的信息保存在關係數據庫中。 按照以前的方式來進行開發就會出現程序員會在本身的業務邏輯代碼中夾雜不少SQL語句用來增長、讀取、修改、刪除相關數據,而這些代碼一般都是重複的。 3、ORM的優點 ORM解決的主要問題是對象和關係的映射。它一般把一個類和一個表一一對應,類的每一個實例對應表中的一條記錄,類的每一個屬性對應表中的每一個字段。 ORM提供了對數據庫的映射,不用直接編寫SQL代碼,只需像操做對象同樣從數據庫操做數據。 讓軟件開發人員專一於業務邏輯的處理,提升了開發效率。 4、ORM的劣勢 ORM的缺點是會在必定程度上犧牲程序的執行效率。 ORM用多了SQL語句就不會寫了,關係數據庫相關技能退化... 5、ORM總結 ORM只是一種工具,工具確實能解決一些重複,簡單的勞動。這是不能否認的。 但咱們不能期望某個工具能一勞永逸地解決全部問題,一些特殊問題仍是須要特殊處理的。 可是在整個軟件開發過程當中須要特殊處理的狀況應該都是不多的,不然所謂的工具也就失去了它存在的意義。 2、Django中的ORM 一、Django項目使用MySQL數據庫 1. 手動新建一個數據庫 2. 在Django項目的settings.py文件中,配置數據庫鏈接信息: DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "你的數據庫名稱", # 須要本身手動建立數據庫 "USER": "數據庫用戶名", "PASSWORD": "數據庫密碼", "HOST": "數據庫IP", "POST": 3306 } } 3. 告訴Django用什麼模塊鏈接MySQL,在和settings.py同級的__init__.py中: import pymysql pymysql.install_as_MySQLdb() 4. 在app下面的models.py中建立類,類必定要繼承models.Model 5.執行兩個命令 1. python manage.py makemigrations --> 判斷models.py中是否有改動,把改動記錄到migrations目錄下 2. python manage.py migrate --> 把改動翻譯成SQL語句去數據庫執行 注意:當項目中不止有一個APP時,python manage.py makemigrations appname 能夠單獨判斷某個app裏面的models.py的變動 2、Model 在Django中model是你數據的單1、明確的信息來源。它包含了你存儲的數據的重要字段和行爲。一般,一個模型(model)映射到一個數據庫表 基本狀況: 每一個模型都是一個Python類,它是django.db.models.Model的子類。 模型的每一個屬性都表明一個數據庫字段。 綜上所述,Django爲您提供了一個自動生成的數據庫訪問API。、 3、說明 ORM定義表 from django.db import models class Book(models.Model): title = models.CharField(max_length=20) publisher = models.CharField(max_length=30) title 和 publisher 是模型的字段。每一個字段被指定爲一個類屬性,每一個屬性映射到一個數據庫列。 上面的模型等於下面的SQL建表語句 CREATE TABLE myapp_book ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(20) NOT NULL, "publisher" varchar(30) NOT NULL ); 表myapp_book的名稱是自動生成的,若是你要自定義表名,須要在model的Meta類中指定 db_table 參數,強烈建議使用小寫表名,特別是使用MySQL做爲後端數據庫時。 id字段是自動添加的,若是你想要指定自定義主鍵,只需在其中一個字段中指定 primary_key=True 便可。若是Django發現你已經明確地設置了Field.primary_key,它將不會添加自動ID列。 Django會根據配置文件中指定的數據庫後端類型來生成相應的SQL語句。 Django支持MySQL5.5及更高版本。 4、字段 總覽
AutoField(Field) - int自增列,必須填入參數 primary_key=True BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 from django.db import models class UserInfo(models.Model): # 自動建立一個列名爲id的且爲自增的整數列 username = models.CharField(max_length=32) class Group(models.Model): # 自定義自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整數 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整數 0 ~ 32767 IntegerField(Field) - 整數列(有符號的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整數 0 ~ 2147483647 BigIntegerField(IntegerField): - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布爾值類型 NullBooleanField(Field): - 能夠爲空的布爾值 CharField(Field) - 字符類型 - 必須提供max_length參數, max_length表示字符長度 TextField(Field) - 文本類型 EmailField(CharField): - 字符串類型,Django Admin以及ModelForm中提供驗證機制 IPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 GenericIPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 - 參數: protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both" URLField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證 URL SlugField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) CommaSeparatedIntegerField(CharField) - 字符串類型,格式必須爲逗號分割的數字 UUIDField(Field) - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 - 參數: path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 FileField(Field) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) DateTimeField(DateField) - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 時間格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 FloatField(Field) - 浮點型 DecimalField(Field) - 10進制小數 - 參數: max_digits,小數總長度 decimal_places,小數位長度 BinaryField(Field) - 二進制類型
經常使用字段 1. AutoField() ***** - int自增列,必須填入參數 primary_key=True - 當model中若是沒有自增列,則自動會建立一個列名爲id的列(即自增的id主鍵) 2. IntegerField ***** - 整數列(有符號的) -2147483648 ~ 2147483647 3. BooleanField - 布爾值類型 4. CharField ***** - 字符類型varchar - 必須提供max_length參數, max_length表示字符長度 5. TextField - 文本類型 6. EmailField - 字符串類型,Django Admin以及ModelForm中提供驗證機制 7. GenericIPAddressField - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 - 參數: protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both" 8. UUIDField ***** - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 9. FileField - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 10. ImageField - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) 11. DateTimeField ***** - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 12. DateField ***** - 日期格式 YYYY-MM-DD 13. TimeField - 時間格式 HH:MM[:ss[.uuuuuu]] 14. FloatField - 浮點型 15. DecimalField ***** - 10進制小數 - 參數: max_digits,小數總長度 decimal_places,小數位長度 五、自定義字段 1.自定義char類型字段: from django.db import models class MycharField(models.Field): """ 自定義的char類型的字段類 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MycharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成數據庫表的字段類型爲char,長度爲length指定的值 """ return 'char(%s)' % self.max_length class UserInfo(models.Model): name = MycharField(max_length=12) 2.自定義無符號整數字段: class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' 3.返回值爲字段在數據庫中的屬性,Django字段默認的值爲:
'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)',
六、字段參數
null 數據庫中字段是否能夠爲空 db_column 數據庫中字段的列名 default 數據庫中字段的默認值 primary_key 數據庫中字段是否爲主鍵 db_index 數據庫中字段是否能夠創建索引 unique 數據庫中字段是否能夠創建惟一索引 unique_for_date 數據庫中字段【日期】部分是否能夠創建惟一索引 unique_for_month 數據庫中字段【月】部分是否能夠創建惟一索引 unique_for_year 數據庫中字段【年】部分是否能夠創建惟一索引 verbose_name Admin中顯示的字段名稱 blank Admin中是否容許用戶輸入爲空 editable Admin中是否能夠編輯 help_text Admin中該字段的提示信息 choices Admin中顯示選擇框的內容,用不變更的數據放在內存中從而避免跨表操做 如:sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3) error_messages 自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能爲空.", 'invalid': '格式錯誤'} validators 自定義錯誤驗證(列表類型),從而定製想要的驗證規則 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '優先錯信息1', 'c2': '優先錯信息2', 'c3': '優先錯信息3', }, validators=[ RegexValidator(regex='root_\d+', message='錯誤了', code='c1'), RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'), EmailValidator(message='又錯誤了', code='c3'), ] )
經常使用字段的參數 1.null 數據庫中字段是否能夠爲空 2.db_column 數據庫中字段的列名 3.default 數據庫中字段的默認值 4.primary_key 數據庫中字段是否爲主鍵 5.db_index 數據庫中字段是否能夠創建索引 6.unique 數據庫中字段是否能夠創建惟一索引 7.unique_for_date 數據庫中字段【日期】部分是否能夠創建惟一索引 8.unique_for_month 數據庫中字段【月】部分是否能夠創建惟一索引 9.unique_for_year 數據庫中字段【年】部分是否能夠創建惟一索引 10.DatetimeField和Datefield獨有的參數: auto_now_add = True --> 當前數據的建立時間 auto_now = True --> 當前數據的最後修改時間 注意:auto_now_add和auto_now 不能寫在同一個字段上 11. 帶choice參數的字段 get_字段名_display() --> 獲取choice字段的顯示值 例如: sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3) get_sex_display() --> 保密 12. 建表的元信息 class Meta: db_table = '表名' unique_together = (('ip', 'port'),) index_together = (("pub_date", "deadline"),) 七、元信息 class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # 數據庫中生成的表名稱默認是app名稱 + 下劃線 + 類名(全小寫) # 能夠經過db_table進行修改 db_table = "userinfo" # 告訴Django這個表名就叫userinfo,不要默認建成 app名稱_userinfo # 聯合索引 index_together = [ ("pub_date", "deadline"), ] # 聯合惟一索引 unique_together = (("ip", "port"),) # admin中顯示的表名稱 verbose_name # verbose_name加s verbose_name_plural 例如: # 博客表 class Blog(models.Model): title = models.CharField(max_length=32) push_time = models.DateTimeField(auto_now_add=True) # 建立時間 edit_time = models.DateTimeField(auto_now=True) # 最後修改時間 class Meta: db_table = 'blog' # 控制建表名稱 # 應用程序表 class Size(models.Model): ip = models.GenericIPAddressField() port = models.IntegerField() class Meta: unique_together = (('ip', 'port'),) 3、ORM的相關操做 小知識:
去manage.py把__name__的下一行,一直到最上面的那幾行代碼複製到一個py文件, import django django.setup() from appname.models import TableName 測試內容
UserInfo表:
class UserInfo(models.Model): name = MycharField(max_length=12) birthday = models.DateTimeField(verbose_name='生日', null=True) sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3) def __str__(self): return self.name
一、基本操做13條(必會) 1-1、返回QuerySet對象(列表)的方法(返回的是列表,列表中的元素是對象) all() 查詢全部結果 filter(**kwargs) 它包含了與所給篩選條件相匹配的對象 exclude(**kwargs) 它包含了與所給篩選條件不匹配的對象 order_by(*field) 對查詢結果排序 reverse() 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。 distinct() 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。) 1-2、特殊的QuerySet(返回的是列表,但列表中的元素不是對象) values(*field) 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列
User.objects.all().values('id', 'name')
QuerySet [{'id': 1, 'name': '小明'}, {'id': 2, 'name': '小東'}] values_list(*field) 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
User.objects.all().values_list('id')
QuerySet [(1, '小明'), (2, '小東')] 1-3、返回具體對象的 get(**kwargs) 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 first() 返回第一條記錄 last() 返回最後一條記錄 1-4、返回布爾值的方法 exists() 若是QuerySet包含數據,判斷表中是否有數據,有就返回True,不然返回False 1-5、返回數字的方法 count() 返回數據庫中匹配查詢(QuerySet)的對象數量。 例子: # all()找到UserInfo表中全部的對象 ret = UserInfo.objects.all() print(ret) # filter()找到名字是小明的那我的 ret1 = UserInfo.objects.filter(name='小明') print(ret1) # exclude()找到名字不是小明的那些人 ret1 = UserInfo.objects.exclude(name='小明') print(ret1) # values()返回的仍是列表,但列表中的不是對象,而是字典 ret = UserInfo.objects.all().values('name', 'sex') print(ret) # values_list()返回的仍是列表,但列表中的不是對象,而是元組 ret1 = UserInfo.objects.all().values_list('name', 'sex') print(ret1) # order_by('xx')根據xx升序排序,order_by('-xx')根據xx降序排序 ret = UserInfo.objects.all().order_by('id') ret1 = UserInfo.objects.all().order_by('-id') ret2 = UserInfo.objects.all().order_by('birthday') print(ret) print(ret1) print(ret2) # reverse() 對排序的結果進行反序 ret = UserInfo.objects.all().order_by('id').reverse() print(ret) # count()返回數量 ret = UserInfo.objects.all().count() print(ret) # first()返回第一條記錄和last()返回最後一條記錄 ret1 = UserInfo.objects.all().first() ret2 = UserInfo.objects.all().last() print(ret1) print(ret2) # exists()判斷表中是否有數據 ret = UserInfo.objects.exists() print(ret) 二、單表查詢之神奇的雙下劃線 # __lt:查詢id值小於3的對象 ret = UserInfo.objects.filter(id__lt=3) print(ret) # __lte:查詢id值小於等於3的對象 ret = UserInfo.objects.filter(id__lte=3) print(ret) # __gt:查詢id值大於3的對象 ret = UserInfo.objects.filter(id__gt=3) print(ret) # __in:id是1,3,5的對象 ret = UserInfo.objects.filter(id__in=[1, 3, 5]) print(ret) # __in:id不是1,3,5的對象 ret = UserInfo.objects.exclude(id__in=[1, 3, 5]) print(ret) # __contains:找到名字包含"小"的對象,__icontains:和__contains同樣,可是不區分大小寫 ret = UserInfo.objects.filter(name__contains='小') print(ret) # __range:找到範圍在[1, 3]之間的對象 ret = UserInfo.objects.filter(id__range=[1, 3]) print(ret) # __endswith:找到以"仔"結尾的對象 ret = UserInfo.objects.filter(name__endswith='仔') print(ret) # date字段還可使用__year、__month等:找到10月出生的人 ret = UserInfo.objects.filter(birthday__month=10) print(ret)
# __isnull:判斷這個字段是否爲空
ret = UserInfo.objects.filter(name__isnull=True)
print(ret) # 雙下還能夠鏈式操做:找到出生小於2000年的 ret = UserInfo.objects.filter(birthday__year__lt=2000) print(ret)