一、django ORM簡介
O(objects):類和對象。R(Relation):關系,關系數據庫中的表格。M(Mapping):映射。
Django ORM框架的功能:
1.建立模型類和表之間的對應關系,允許我們通過面向對象的方式來操作數據庫。
2.根據設計的模型類生成數據庫中的表格。
3.通過方便的配置就可以進行數據庫的切換。
二、 數據庫的配置
Django可以配置使用sqlite3,mysql,oracle,postgresql等數據庫。Django默認使用的是sqlite3數據庫,settigs.py里面:
DATABASES = {
? ? 'default': {
? ? ? ? 'ENGINE': 'django.db.backends.sqlite3',#默認使用的數據庫引擎是sqlite3,項目自動創建
? ? ? ? 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),#指定數據庫所在的路徑
? ? }
}
Django項目也可以配置使用mysql數據庫,使用如下配置:
DATABASES = {
? ? 'default': {
? ? ? ? 'ENGINE': 'django.db.backends.mysql',#表示使用的是mysql數據庫的引擎
? ? ? ? 'NAME': 'db1',? ? ? #數據庫的名字,可以在mysql的提示符下先創建好
? ? ? ? 'USER':'root',? ? ? #數據庫用戶名
? ? ? ? 'PASSWORD':'',? ? ? #數據庫密碼
? ? ? ? 'HOST':'',? ? ? ? ? #數據庫主機,留空默認為"localhost"
? ? ? ? 'PORT':'3306',? ? ? #數據庫使用的端口
? ? }
}
配置好數據庫的信息后還必須安裝數據庫的驅動程序,Django默認導入的mysql的驅動程序是MySQLdb,然而MySQLdb對于py3支持不全,所以這里使用PyMySQL。
pip install pymysql
在項目名文件下的__init__.py文件中寫入如下配置:
import pymysql
pymysql.install_as_MySQLdb()
三、創建數據庫表結構文件
對應app目錄下的models.py
1、生成一個簡單的數據庫表:
在未指定primary_key的情況下,Django會默認創建一個id自增字段作為主鍵。
from django.db import models
class Account(models.Model):
? ? account_name = models.CharField(max_length=20)
? ? account_id = models.IntegerField(primary_key=True)
? ? balance = models.DecimalField(max_digits=2, decimal_places=2)
2、執行命令生成到數據庫
python manage.py makemigrations
python manage.py migrate # 生成數據表
四、數據庫字段
AutoField(Field) - int自增列,必須填入參數 primary_key=True
BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True
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)- 二進制類型
五、數據庫字段參數
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中顯示選擇框的內容,用不變動的數據放在內存中從而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
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'), ]
)
六、數據庫Meta元信息
class UserInfo(models.Model):
? ? ? ? nid = models.AutoField(primary_key=True)
? ? ? ? username = models.CharField(max_length=32)
? ? ? ? class Meta:
? ? ? ? ? ? # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名
? ? ? ? ? ? db_table = "table_name"
? ? ? ? ? ? # 聯合索引
? ? ? ? ? ? index_together = [
? ? ? ? ? ? ? ? ("pub_date", "deadline"),
? ? ? ? ? ? ]
? ? ? ? ? ? # 聯合唯一索引
? ? ? ? ? ? unique_together = (("driver", "restaurant"),)
? ? ? ? ? ? # admin中顯示的表名稱
? ? ? ? ? ? verbose_name
? ? ? ? ? ? # verbose_name加s
? ? ? ? ? ? verbose_name_plural
七、關系字段
關系字段用于保存數據表之間的關系,包括ForeignKey, ManyToManyField等。
1、ForeignKey
ForeignKey(ForeignObject) # ForeignObject(RelatedField)
? ? ? ? to,? ? ? ? ? ? ? ? ? ? ? ? # 要進行關聯的表名
? ? ? ? to_field=None,? ? ? ? ? ? ? # 要關聯的表中的字段名稱
? ? ? ? on_delete=None,? ? ? ? ? ? # 當刪除關聯表中的數據時,當前表與其關聯的行的行為
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.CASCADE,刪除關聯數據,與之關聯也刪除
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.DO_NOTHING,刪除關聯數據,引發錯誤IntegrityError
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.PROTECT,刪除關聯數據,引發錯誤ProtectedError
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.SET_NULL,刪除關聯數據,與之關聯的值設置為null(前提FK字段需要設置為可空)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.SET_DEFAULT,刪除關聯數據,與之關聯的值設置為默認值(前提FK字段需要設置默認值)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - models.SET,刪除關聯數據,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? a. 與之關聯的值設置為指定值,設置:models.SET(值)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? b. 與之關聯的值設置為可執行對象的返回值,設置:models.SET(可執行對象)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? def func():
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 10
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class MyModel(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? user = models.ForeignKey(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? to="User",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? to_field="id"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? on_delete=models.SET(func),)
? ? ? ? related_name=None,? ? ? ? ? # 反向操作時,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
? ? ? ? related_query_name=None,? ? # 反向操作時,使用的連接前綴,用于替換【表名】? ? 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
? ? ? ? limit_choices_to=None,? ? ? # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 如:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to={'nid__gt': 5}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=lambda : {'nid__gt': 5}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? from django.db.models import Q
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=Q(nid__gt=10)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
? ? ? ? db_constraint=True? ? ? ? ? # 是否在數據庫中創建外鍵約束
? ? ? ? parent_link=False? ? ? ? ? # 在Admin中是否顯示關聯數據
2、OneToOneField
OneToOneField(ForeignKey)
? ? ? ? to,? ? ? ? ? ? ? ? ? ? ? ? # 要進行關聯的表名
? ? ? ? to_field=None? ? ? ? ? ? ? # 要關聯的表中的字段名稱
? ? ? ? on_delete=None,? ? ? ? ? ? # 當刪除關聯表中的數據時,當前表與其關聯的行的行為
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ###### 對于一對一 ######
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 1. 一對一其實就是 一對多 + 唯一索引
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 2.當兩個類之間有繼承關系時,默認會創建一個一對一字段
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 如下會在A表中額外增加一個c_ptr_id列且唯一:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class C(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nid = models.AutoField(primary_key=True)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? part = models.CharField(max_length=12)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class A(C):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id = models.AutoField(primary_key=True)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? code = models.CharField(max_length=1)
3、ManyToManyField
ManyToManyField(RelatedField)
? ? ? ? to,? ? ? ? ? ? ? ? ? ? ? ? # 要進行關聯的表名
? ? ? ? related_name=None,? ? ? ? ? # 反向操作時,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
? ? ? ? related_query_name=None,? ? # 反向操作時,使用的連接前綴,用于替換【表名】? ? 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
? ? ? ? limit_choices_to=None,? ? ? # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 如:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to={'nid__gt': 5}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=lambda : {'nid__gt': 5}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? from django.db.models import Q
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=Q(nid__gt=10)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
? ? ? ? symmetrical=None,? ? ? ? ? # 僅用于多對多自關聯時,symmetrical用于指定內部是否創建反向操作的字段
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 做如下操作時,不同的symmetrical會有不同的可選字段
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? models.BB.objects.filter(...)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 可選字段有:code, id, m1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class BB(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? code = models.CharField(max_length=12)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? m1 = models.ManyToManyField('self',symmetrical=True)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 可選字段有: bb, code, id, m1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class BB(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? code = models.CharField(max_length=12)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? m1 = models.ManyToManyField('self',symmetrical=False)
? ? ? ? through=None,? ? ? ? ? ? ? # 自定義第三張表時,使用字段用于指定關系表
? ? ? ? through_fields=None,? ? ? ? # 自定義第三張表時,使用字段用于指定關系表中那些字段做多對多關系表
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? from django.db import models
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Person(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name = models.CharField(max_length=50)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Group(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name = models.CharField(max_length=128)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? members = models.ManyToManyField(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Person,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? through='Membership',
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? through_fields=('group', 'person'),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? )
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Membership(models.Model):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? group = models.ForeignKey(Group, on_delete=models.CASCADE)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? person = models.ForeignKey(Person, on_delete=models.CASCADE)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? inviter = models.ForeignKey(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Person,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? on_delete=models.CASCADE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? related_name="membership_invites",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? )
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? invite_reason = models.CharField(max_length=64)
? ? ? ? db_constraint=True,? ? ? ? # 是否在數據庫中創建外鍵約束
? ? ? ? db_table=None,? ? ? ? ? ? ? # 默認創建第三張表時,數據庫中表的名稱
八、數據庫基本操作
?#創建一個書的類,繼承models類
class Book(models.Model):
? ? #用models類創建書的名字,類型為字符串,CharField相當于mysql語句中的varchar,字段最長為32
? ? title = models.CharField(max_length=32)
? ? #創建書的價格,類型為浮點型,小數點前最長4位,小數點后最長2位
? ? price = models.DecimalField(max_digits=6, decimal_places=2)
? ? #創建書的出版社信息,其與出版社的外鍵關系為一對多,所以用外鍵
? ? publish = models.ForeignKey(Publish)
? ? #創建書的出版日期,類型為日期
? ? publication_date = models.DateField()
? ? #創建書的類型信息,為字符串類型,最長為20
? ? classification=models.CharField(max_length=20)
? ? #創建書的作者信息,書籍與作者的關系為多對多,所以使用many-to-many
? ? authors = models.ManyToManyField("Author")
?
1、增
1.1一對一信息的創建
a、使用create方式
方式一: Publish.objects.create("name"="人民出版社",city="北京"}
方式二: Publish.objects.create(**{"name":"文藝出版社","city":"上海"}}
b、使用save方式
方式一:
book1=Book(title="python",price="88",publish_id="1",publication_date="2017-06-18")
book1.save()
方式二:
author1=Author(name="jerry")
author1.save()
1.2一對多的信息的創建(Foreignkey)
方式一:
#獲取出版社對象
publish_obj=Publish.objects.get(id=4)?
#將出版社的對象綁定到書籍的記錄中
Book.objects.create(
? ? title="python",
? ? price=48.00,
? ? publication_date="2017-07-12",
? ? publish=publish_obj,
)?
方式二:
#直接把出版社的id號插入到書籍的記錄中
Book.objects.create(
? ? title="python",
? ? price=48.00,
? ? publish_id=2,
? ? publication_date="2017-06-18",
)
1.3多對多信息的創建(ManyToManyField())
a、為一本書添加多個作者
author1=Author.objects.get(id=1)#獲取id號為1的作者對象
author2=Author.objects.filter(name="tom")#獲取名字為"tom"的作者對象
book1=Book.objects.get(id=2)#獲取id號為2的書籍對象
book1.authors.add(author1,author2)#為書籍對象添加多個作者對象
也可以用這種方式:
book1.authors.add(*[author1,author2])#為書籍對象添加作者對象的列表
book1.authors.remove(*[author1,author2])#刪除指定書籍的所有作者
b、為一個作者添加多本書
author_obj = Author.objects.filter(name="jerry")#獲取名字為"jerry"的作者對象
book_obj=Book.objects.filter(id__gt=3)#獲取id大于3的書籍對象集合
author_obj.book_set.add(*book_obj)#為作者對象添加書籍對象集合
author_obj.book_set.remove(*book_obj)#刪除指定作者對象所有的書籍
使用models.ManyToManyField()會自動創建第三張表
1.4手動創建多對多的作者與書籍信息表
class Book2Author(models.Models):
? ? author=models.ForeignKey("Author")#為作者指定Author這張表做為外鍵
? ? book=models.ForeignKey("Book")#為書籍指定Book這張表做為外鍵
author_obj=models.Author.objects.filter(id=3)[0]#獲取Author表中id為3的作者對象
book_obj=models.Book.objects.filter(id=4)[0]#獲取Book表中id為4的書籍對象
方式一:
obj1=Book2Author.objects.create(author=author_obj,book=book_obj)
obj1.save()
方式二:
obj2=Book2Author(author=author_obj,book=book_obj)
obj2.save()
2、刪
Book.objects.filter(id=1).delete()
3、改
3.1使用save方法將所有屬性重新設定一遍,效率低
author1=Author.objects.get(id=3)#獲取id為3的作者對象
author1.name="jobs"#修改作者對象的名字
author1.save()#把更改寫入數據庫
3.2使用update方法直接設置對就的屬性
Publish.objects.filter(id=2).update(name="北京出版社")
注意:update()是QuerySet對象的一個方法,get返回的是一個model對象,其沒有update方法.
filter返回的是一個QuerySet對象,filter里可以設定多個過濾條件
4、查
查詢數據使用QuerySet API。 QuerySet是惰性執行的,創建Query Set不會訪問數據庫,只有在訪問具體查詢結果的時候才會訪問數據庫。
4.1查詢方法:
filter(**kwargs)? ? ? ? ? ? 包含了與所給篩選條件相匹配的對象
all()? ? ? ? ? ? ? ? ? ? ? 查詢所有結果
get(**kwargs)? ? ? ? ? ? ? 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,如果符合篩選條件的對象超過一個或者沒有都是報錯
values(*field)? ? ? ? ? ? ? 返回一個ValueQuerySet,運行后得到的并不是一系列model的實例化對象,而是一個可迭代的字典序列
exclude(**kwargs)? ? ? ? ? 包含了與所給的篩選條件不匹配的對象
order by(*field)? ? ? ? ? ? 對查詢結果排序
reverse()? ? ? ? ? ? ? ? ? 對查詢結果反向排序
distinct()? ? ? ? ? ? ? ? ? 從返回結果中剔除重復記錄
values_list(*field)? ? ? ? 與values()非常相似,返回一個元組序列,values返回一個字典序列
count()? ? ? ? ? ? ? ? ? ? 返回數據庫中匹配的記錄的數量
first()? ? ? ? ? ? ? ? ? ? 返回數據庫中匹配的對象的第一個對象
last()? ? ? ? ? ? ? ? ? ? ? 返回數據庫中匹配的對象的最后一個對象
exists()? ? ? ? ? ? ? ? ? ? 判斷一個對象集合中是否包含指定對象,包含返回True,不包含返回False
exclude()? ? ? ? ? ? 排除滿足條件的對象
annotate()? ? ? ? ? ? 使用聚合函數
dates()? ? ? ? ? ? ? ? 根據日期獲取查詢集
datetimes()? ? ? ? ? ? 根據時間獲取查詢集
none()? ? ? ? ? ? ? ? 創建空的查詢集
union()? ? ? ? ? ? ? ? 并集
intersection()? ? ? ? 交集
difference()? ? ? ? 差集
select_related()? ? 附帶查詢關聯對象
prefetch_related()? ? 預先查詢
extra()? ? ? ? ? ? ? ? 附加SQL查詢
defer()? ? ? ? ? ? ? ? 不加載指定字段
only()? ? ? ? ? ? ? ? 只加載指定的字段
using()? ? ? ? ? ? ? ? 選擇數據庫
select_for_update()? ? 鎖住選擇的對象,直到事務結束。
raw()? ? ? ? ? ? ? ? 接收一個原始的SQL查詢
1.filter():
??? filter(**kwargs)
??? 返回滿足查詢參數的對象集合。
??? 查找的參數(**kwargs)應該滿足下文字段查找中的格式。多個參數之間是和AND的關系。
??? Student.objects.filter(age__lt=10)#查詢滿足年齡小于10歲的所有學生對象
2.exclude():
??? exclude(**kwargs)
??? 返回一個新的QuerySet,它包含不滿足給定的查找參數的對象
??? Student.objects.exclude(age__gt=20, name='lin')#排除所有年齡大于20歲且名字為“lin”的學員集
3.annotate():
??? nnotate(args, *kwargs)
??? 使用提供的聚合表達式查詢對象。
??? 表達式可以是簡單的值、對模型(或任何關聯模型)上的字段的引用或者聚合表達式(平均值、總和等)。
??? annotate()的每個參數都是一個annotation,它將添加到返回的QuerySet每個對象中。
??? 關鍵字參數指定的Annotation將使用關鍵字作為Annotation 的別名。 匿名參數的別名將基于聚合函數的名稱和模型的字段生成。 只有引用單個字段的聚合表達式才可以使用匿名參數。 其它所有形式都必須用關鍵字參數。
??? 例如,如果正在操作一個Blog列表,你可能想知道每個Blog有多少Entry:
??? >>> from django.db.models import Count
??? >>> q = Blog.objects.annotate(Count('entry'))
??? # The name of the first blog
??? >>> q[0].name
??? 'Blogasaurus'
??? # The number of entries on the first blog
??? >>> q[0].entry__count
??? 42
4.order_by():
??? order_by(*fields)
??? 默認情況下,根據模型的Meta類中的ordering屬性對QuerySet中的對象進行排序
??? Student.objects.filter(school="陽關小學").order_by('-age', 'name')
??? 上面的結果將按照age降序排序,然后再按照name升序排序。"-age"前面的負號表示降序順序。 升序是默認的。 要隨機排序,使用"?",如下所示:
??? Student.objects.order_by('?')
5. reverse():
??? reverse()????
??? 反向排序QuerySet中返回的元素。 第二次調用reverse()將恢復到原有的排序。????
??? 如要獲取QuerySet中最后五個元素,可以這樣做:???
??? my_queryset.reverse()[:5]???
??? 這與Python直接使用負索引有點不一樣。 Django不支持負索引。
6.distinct():
??? distinct(*fields)
??? 去除查詢結果中重復的行。?
??? 默認情況下,QuerySet不會去除重復的行。當查詢跨越多張表的數據時,QuerySet可能得到重復的結果,這時候可以使用distinct()進行去重。
7. values():
??? values(fields, *expressions)????
??? 返回一個包含數據的字典的queryset,而不是模型實例。????
??? 每個字典表示一個對象,鍵對應于模型對象的屬性名稱。如:????
??? # 列表中包含的是Student對象
??? >>> Student.objects.filter(name__startswith='Lin')
??? <QuerySet [<Student: Lin Student>]>????
??? # 列表中包含的是數據字典
??? >>> Student.objects.filter(name__startswith='Lin').values()
??? <QuerySet [{'id': 1, 'name': 'Linxiao', 'age': 20}]>????
??? 另外該方法接收可選的位置參數*fields,它指定values()應該限制哪些字段。如果指定字段,每個字典將只包含指定的字段的鍵/值。如果沒有指定字段,每個字典將包含數據庫表中所有字段的鍵和值。如下:
??? >>> Student.objects.filter(name__startswith='Lin').values()
??? <QuerySet [{'id': 1, 'name': 'Linxiao', 'age': 20}]>
??? >>> Blog.objects.values('id', 'name')
??? <QuerySet [{'id': 1, 'name': 'Linxiao'}]>
8.values_list():
??? values_list(*fields, flat=False)?? ?
??? 與values()類似,只是在迭代時返回的是元組而不是字典。每個元組包含傳遞給values_list()調用的相應字段或表達式的值,因此第一個項目是第一個字段等。 像這樣:
??? >>> Student.objects.values_list('id', 'name')
獲取數據表的全部數據記錄:
Account.objects.all()
返回值可以進行切片,但不支持負索引。或者使用:
Account.objects.get(field_name=val)
示例:
Account.objects.get(account_name='john')
或者使用過濾器查詢多條記錄:
??? Account.objects.filter(accounnt_name=val)
??? 嚴格等于
??? Account.objects.filter(account_name__iexact=val)
??? 忽略大小寫
??? Account.objects.filter(account_name__contains=val)
??? 名稱中包含val
??? Account.objects.filter(account_name__icontains=val)
??? 忽略大小寫,包含
??? Account.objects.filter(account_name__regex=val)
??? 正則表達式
??? Account.objects.filter(account_name__iregex=val)
??? 正則表達式,忽略大小寫
與filter相反exclude用于返回不滿足條件的查詢結果。
Account.objects.exclude(account_name__contains=val)
filter與exclude可以進行鏈式查詢
Account.objects.exclude(account_name__contains='john').exlucde(balance=0)
對于查詢結果可以使用distinct()去重或者使用order_by(field)進行排序。
Account.objects.filter(account_name__regex=val).distinct()
Account.objects.filter(account_name__regex=val).oreder_by('balance')
使用reverse()方法可以反轉結果集中的元素順序,調用兩次將會恢復原順序。
從SQL 的角度,QuerySet和SELECT 語句等價,過濾器是像WHERE 和LIMIT 一樣的限制子句。
like:
? ? __exact? ? ? ? 精確等于? ? ? like 'aaa'
? ? __iexact? ? ? 精確等于? ? ? 忽略大小寫 ilike 'aaa'
? ? __contains? ? 包含? ? ? ? ? like '%aaa%'
? ? __icontains? ? 包含,忽略大小寫 ilike '%aaa%',但是對于sqlite來說,contains的作用效果等同于icontains。
in:
? ? __in
? ? 查詢在某一范圍的書
? ? Book.objects.filter(publish__in=[10, 20, 30])
is null / is not null:
? ? __isnull? 判空
? ? Book.objects.filter(name__isnull=True)? ? // 查詢用戶名為空的書
? ? Publish.objects.filter(name__isnull=False)? // 查詢用戶名不為空的書
不等于/不包含于:
? ? Book.objects.filter().excute(publishe=10)? ? // 查詢出版社不為10的書
? ? Book.objects.filter().excute(publish__in=[10, 20])? // 查詢出版社不在 [10, 20] 的書
其他常用模糊查詢:
? ? __startswith 以…開頭
? ? __istartswith 以…開頭 忽略大小寫
? ? __endswith 以…結尾
? ? __iendswith 以…結尾,忽略大小寫
? ? __range 在…范圍內
? ? __year 日期字段的年份
? ? __month 日期字段的月份
? ? __day 日期字段的日
4.2雙下劃線(__)查詢
a、雙下劃線(__)之單表條件查詢
例子:
table1.objects.filter(id__lt=10,id__gt=1)#獲取id小于10,且大于1的記錄
table1.objects.filter(id__in=[11,22,33,44])#獲取id在[11,22,33,44]中的記錄
table1.objects.exclude(id__in=[11,22,33,44])#獲取id不在[11,22,33,44]中的記錄
table1.objects.filter(name__contains="content1")#獲取name中包含有"contents"的記錄(區分大小寫)
table1.objects.filter(name__icontains="content1")#獲取name中包含有"content1"的記錄(不區分大小寫)
table1.objects.filter(id__range=[1,4])#獲取id在1到4(不包含4)之間的的記錄
b、雙下劃線(__)之多表條件查詢
正向查找(條件)之一對一查詢
#查詢書名為"python"的書的id號
res3=Book.objects.filter(title="python").values("id")
print(res3)
正向查找(條件)之一對多查詢
#查詢書名為"python"的書對應的出版社的地址
res4=Book.objects.filter(title="python").values("publisher__city")
print(res4)
#查詢"aaa"作者所寫的所有的書的名字
res5=Book.objects.filter(author__name="aaa").values("title")
print(res5)
#查詢"aaa"作者所寫的所有的書的名字(與上面的用法沒區別)
res6=Book.objects.filter(author__name="aaa").values("title")
print(res6)
反向查找之一對多查詢
#查詢出版了書名為"python"這本書的出版社的名字
res7=Publisher.objects.filter(book__title="python").values("name")
print(res7)
#查詢寫了書名為"python"的作者的名字
res8=Publisher.objects.filter(book__title="python").values("book__authors")
print(res8)
反向查找之多對多查詢
#查詢所寫的書名為"python"的作者的名字
res9=Author.objects.filter(bool__title="python").values("name")
print(res9)
條件查詢即與對象查詢對應,是指filter,values等方法中的通過__來明確查詢條件
4.3F查詢和Q查詢
F查詢專門取對象中某列值的操作,F的作用:用來批量修改數據的
#導入F
from django.db.models import F
#把table1表中的num列中的每一個值在的基礎上加10
table1.objects.all().update(num=F("num")+10)
Q構建搜索條件,?Q的作用:Q是用來做條件查詢的
#導入Q
from django.db.models import Q
Q對象可以對關鍵字參數進行封裝,從而更好的應用多個查詢
#查詢table2表中以"aaa"開頭的所有的title列
q1=table2.objects.filter(Q(title__startswith="aaa")).all()
print(q1)
Q對象可以組合使用&,|操作符,當一個操作符是用于兩個Q對象時,會產生一個新的Q對象
#查找以"aaa"開頭,或者以"bbb"結尾的所有title
Q(title__startswith="aaa") | Q(title__endswith="bbb")
Q對象可以用"~"操作符放在表達式前面表示否定,也可允許否定與不否定形式的組合
#查找以"aaa"開頭,且不以"bbb"結尾的所有title
Q(title__startswith="aaa") & ~Q(title__endswith="bbb")
Q對象可以與關鍵字參數查詢一起使用,Q對象放在關鍵字查詢參數的前面
查詢條件:
#查找以"aaa"開頭,以"bbb"結尾的title且書的id號大于4的記錄
Q(title__startswith="aaa") | Q(title__endswith="bbb"),book_id__gt=4
九、實例
1、Django的ORM中如何判斷查詢結果是否為空,判斷django中的orm為空
result= Booking.objects.filter()
方法一 .exists()
if result.exists():
? ? print "QuerySet has Data"
else:
? ? print "QuerySet is empty"
方法二 .count()==0
if result.count() == 0:
? ? print "empty"
方法三
if result:
? ? print "QuerySet has Data"
else:
? ? print "QuerySet is empty"
總結:
QuerySet.exists() > QuerySet.count()==0 > QuerySet
2、模板中顯示數據庫內容的方法
?a、創建數據庫
from django.db import models
from django.db import models
class Business(models.Model):
? ? caption = models.CharField(max_length=32)
? ? code = models.CharField(max_length=32)
class Host(models.Model):
? ? nid = models.AutoField(primary_key=True)
? ? hostname = models.CharField(max_length=32,db_index=True)
? ? ip = models.GenericIPAddressField(protocol='both',db_index=True)
? ? port = models.IntegerField()
? ? business = models.ForeignKey(to='Business',to_field='id',on_delete=models.CASCADE)
business.html
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>Title</title>
</head>
<body>
? ? <h1>業務線列表(對象)</h1>
? ? <ul>
? ? ? ? {% for row in v1 %}
? ? ? ? ? ? <li>{{ row.id }}-{{ row.caption }}-{{ row.code }}</li>
? ? ? ? {% endfor %}
? ? </ul>
? ? <h1>業務線列表(字典)</h1>
? ? <ul>
? ? ? ? {% for row2 in v2 %}
? ? ? ? ? ? <li>{{ row2.id }}-{{ row2.caption }}</li>
? ? ? ? {% endfor %}
? ? </ul>
</body>
</html>
host.html
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>Title</title>
</head>
<body>
? ? <h1>主機列表(對象)</h1>
? ? <table border="1">
? ? ? ? <tread>
? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? <th>主機ID</th>
? ? ? ? ? ? ? ? <th>IP</th>
? ? ? ? ? ? ? ? <th>端口</th>
? ? ? ? ? ? ? ? <th>業務線名稱</th>
? ? ? ? ? ? </tr>
? ? ? ? </tread>
? ? ? ? <tbody>
? ? ? ? ? ? {% for row in v1 %}
? ? ? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? ? ? <td>{{ row.hostname }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.ip }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.port }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.business.caption }}</td>
? ? ? ? ? ? ? ? </tr>
? ? ? ? ? ? {% endfor %}
? ? ? ? </tbody>
? ? </table>
? ? <h1>主機列表(字典)</h1>
? ? <table border="1">
? ? ? ? <tread>
? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? <th>主機ID</th>
? ? ? ? ? ? ? ? <th>主機名</th>
? ? ? ? ? ? ? ? <th>業務線ID</th>
? ? ? ? ? ? ? ? <th>業務線名稱</th>
? ? ? ? ? ? </tr>
? ? ? ? </tread>
? ? ? ? <tbody>
? ? ? ? ? ? {% for row in v2 %}
? ? ? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? ? ? <td>{{ row.nid }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.hostname }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.business__id }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.business__caption }}</td>
? ? ? ? ? ? ? ? </tr>
? ? ? ? ? ? {% endfor %}
? ? ? ? </tbody>
? ? </table>
? ? <h1>主機列表(元祖)</h1>
? ? <table border="1">
? ? ? ? <tread>
? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? <th>主機ID</th>
? ? ? ? ? ? ? ? <th>主機名</th>
? ? ? ? ? ? ? ? <th>業務線ID</th>
? ? ? ? ? ? ? ? <th>業務線名稱</th>
? ? ? ? ? ? </tr>
? ? ? ? </tread>
? ? ? ? <tbody>
? ? ? ? ? ? {% for row in v3 %}
? ? ? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? ? ? <td>{{ row.0 }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.1 }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.2 }}</td>
? ? ? ? ? ? ? ? ? ? <td>{{ row.3 }}</td>
? ? ? ? ? ? ? ? </tr>
? ? ? ? ? ? {% endfor %}
? ? ? ? </tbody>
? ? </table>
</body>
</html>
views.py
from django.shortcuts import render,HttpResponse
from app01 import models
def business(request):
? ? # 第一種方式(是個對象)
? ? v1 = models.Business.objects.all()
? ? # 第二種方式,只取id和caption(是個字典)
? ? v2 = models.Business.objects.all().values('id','caption')
? ? return render(request,'business.html',{'v1':v1,'v2':v2})
def host(request):
? ? #總共三種方式,對象,字典,列表
? ? v1 = models.Host.objects.all()
? ? v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','business__id','business__caption')
? ? v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','business__id','business__caption')
? ? return render(request,'host.html',{'v1':v1,'v2':v2,'v3':v3})