每一個字段有一些特有的參數,例如,CharField須要max_length參數來指定VARCHAR數據庫字段的大小。還有一些適用於全部字段的通用參數。 這些參數在文檔中有詳細定義,這裏咱們只簡單介紹一些最經常使用的:php
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 自定義無符號整數字段 class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' PS: 返回值爲字段在數據庫中的屬性,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)', 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 數據庫中字段的列名 db_tablespace 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'), ] )
class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # django之後再作數據庫遷移時,再也不爲UserInfo類建立相關的表以及表結構了。 # 此類能夠當作"父類",被其餘Model類繼承。 abstract = True # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名 db_table = "table_name" # 聯合索引 index_together = [ ("pub_date", "deadline"), ] # 聯合惟一索引 unique_together = (("driver", "restaurant"),) # admin中顯示的表名稱 verbose_name # verbose_name加s verbose_name_plural 更多:https: // docs.djangoproject.com / en / 1.10 / ref / models / options /
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中是否顯示關聯數據 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) 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, # 自定義第三張表時,使用字段用於指定關係表中那些字段作多對多關係表 db_constraint = True, # 是否在數據庫中建立外鍵約束 db_table = 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) """ 與普通的多對多不同,使用自定義中間表的多對多不能使用add(), create(),remove(),和set()方法來建立、刪除關係 beatles = Group.objects.create(name="The Beatles") >>> # 無效 >>> beatles.members.add(john) >>> # 無效 >>> beatles.members.create(name="George Harrison") >>> # 無效 >>> beatles.members.set([john, paul, ringo, george]) 可是,clear()方法是有效的,它能清空全部的多對多關係。 >>> # 有效 >>> beatles.members.clear() 一旦經過建立中間模型實例的方法創建了多對多的關聯,你馬上就能夠像普通的多對多那樣進行查詢操做: """
# 獲取個數 # # models.Tb1.objects.filter(name='seven').count() # 大於,小於 # # models.Tb1.objects.filter(id__gt=1) # 獲取id大於1的值 # models.Tb1.objects.filter(id__gte=1) # 獲取id大於等於1的值 # models.Tb1.objects.filter(id__lt=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lte=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # isnull # Entry.objects.filter(pub_date__isnull=True) # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and # 其餘相似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # group by # # from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" # limit 、offset # # models.Tb1.objects.all()[10:20] # regex正則匹配,iregex 不區分大小寫 # # Entry.objects.get(title__regex=r'^(An?|The) +') # Entry.objects.get(title__iregex=r'^(an?|the) +') # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) # hour # # Event.objects.filter(timestamp__hour=23) # Event.objects.filter(time__hour=5) # Event.objects.filter(timestamp__hour__gte=12) # minute # # Event.objects.filter(timestamp__minute=29) # Event.objects.filter(time__minute=46) # Event.objects.filter(timestamp__minute__gte=29) # second # # Event.objects.filter(timestamp__second=31) # Event.objects.filter(time__second=2) # Event.objects.filter(timestamp__second__gte=31)
# extra # # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) # F # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) # Q # # 方式一: # Q(nid__gt=10) # Q(nid=8) | Q(nid__gt=10) # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') # 方式二: # con = Q() # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1.children.append(('id', 9)) # q2 = Q() # q2.connector = 'OR' # q2.children.append(('c1', 1)) # q2.children.append(('c1', 10)) # q2.children.append(('c1', 9)) # con.add(q1, 'AND') # con.add(q2, 'AND') # # models.Tb1.objects.filter(con) # 執行原生SQL # # from django.db import connection, connections # cursor = connection.cursor() # cursor = connections['default'].cursor() # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) # row = cursor.fetchone()
on_delete=None, # 刪除關聯表中的數據時,當前表與其關聯的field的行爲 on_delete=models.CASCADE, # 刪除關聯數據,與之關聯也刪除 on_delete=models.DO_NOTHING, # 刪除關聯數據,什麼也不作 on_delete=models.PROTECT, # 刪除關聯數據,引起錯誤ProtectedError # models.ForeignKey('關聯表', on_delete=models.SET_NULL, blank=True, null=True) on_delete=models.SET_NULL, # 刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空,一對一同理) # models.ForeignKey('關聯表', on_delete=models.SET_DEFAULT, default='默認值') on_delete=models.SET_DEFAULT, # 刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值,一對一同理) on_delete=models.SET, # 刪除關聯數據, ———————————————— 版權聲明:本文爲CSDN博主「buxianghejiu」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/buxianghejiu/article/details/79086011
建立名爲app01的app,在app01下的models.py中建立模型:html
1
2
3
4
5
6
7
8
9
10
11
|
from
django.db
import
models
# Create your models here.
class
Book(models.Model):
id
=
models.AutoField(primary_key
=
True
)
title
=
models.CharField(max_length
=
32
,unique
=
True
)
pub_date
=
models.DateField()
price
=
models.DecimalField(max_digits
=
8
,decimal_places
=
2
)
# 999999.99
publish
=
models.CharField(max_length
=
32
)
def
__str__(
self
):
return
self
.title
|
若想將模型轉爲mysql數據庫中的表,須要在settings中配置:前端
1
2
3
4
5
6
7
8
9
10
|
DATABASES
=
{
'default'
: {
'ENGINE'
:
'django.db.backends.mysql'
,
'NAME'
:
'orm9'
,
# 要鏈接的數據庫,鏈接前須要建立好
'USER'
:
'root'
,
# 鏈接數據庫的用戶名
'PASSWORD'
:'',
# 鏈接數據庫的密碼
'HOST'
:
'127.0.0.1'
,
# 鏈接主機,默認本級
'PORT'
:
3306
,
# 端口 默認3306
}
}
|
確保配置文件中的INSTALLED_APPS中寫入咱們建立的app名稱python
1
2
3
4
5
6
7
8
9
|
INSTALLED_APPS
=
[
'django.contrib.admin'
,
'django.contrib.auth'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
"app01"
,
]
|
django默認導入的驅動是MySQLdb,但是MySQLdb 對於py3有很大問題,咱們須要的驅動是PyMySQL 因此,咱們只須要找到項目名文件下的__init__,在裏面寫入:mysql
1
2
|
import
pymysql
pymysql.install_as_MySQLdb()
|
1
2
|
python manage.py makemigrations
python manage.py migrate
|
1
2
3
4
5
|
#在settings.py中:
STATIC_URL
=
'/static/'
STATICFILES_DIRS
=
(
os.path.join(BASE_DIR,
'static'
),
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
LOGGING
=
{
'version'
:
1
,
'disable_existing_loggers'
:
False
,
'handlers'
: {
'console'
:{
'level'
:
'DEBUG'
,
'class'
:
'logging.StreamHandler'
,
},
},
'loggers'
: {
'django.db.backends'
: {
'handlers'
: [
'console'
],
'propagate'
:
True
,
'level'
:
'DEBUG'
,
},
}
}
|
1
2
|
import
pymysql
pymysql.install_as_MySQLdb()
|
1
2
|
if
version < (
1
,
3
,
3
):
raise
ImproperlyConfigured(
"mysqlclient 1.3.3 or newer is required; you have %s"
%
Database.__version__)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#app01.views.py
from
django.shortcuts
import
render,HttpResponse
from
app01.models
import
Book
def
index(request):
# ==================================添加表記錄 ==================================
# 方式1:
# book_obj=Book(id=1,title="python",price=100,pub_date="2012-12-12",publish="人民出版社")
# book_obj.save()
#方式2: create返回值就是當前生成的對象紀錄
book_obj
=
Book.objects.create(title
=
"php2"
,price
=
100
,pub_date
=
"2013-12-12"
,publish
=
"人民出版社"
)
print
(book_obj.title)
print
(book_obj.price)
print
(book_obj.pub_date)
return
HttpResponse(
"OK"
)
#方式3: 批量導入:
book_list
=
[]
for
i
in
range
(
100
):
book
=
Book(title
=
"book_%s"
%
i,price
=
i
*
i)
book_list.append(book)
Book.objects.bulk_create(book_list)
|
1
2
3
4
5
6
7
8
9
10
11
|
#app01.views.py
from
django.shortcuts
import
render,HttpResponse
from
app01.models
import
Book
def
index(request):
# ==================================刪除表紀錄=================================
# delete: 調用者: queryset對象 model對象
ret
=
Book.objects.
filter
(price
=
100
).delete()
print
(ret)
ret2
=
Book.objects.
filter
(price
=
100
).first().delete()
print
(ret2)
return
HttpResponse(
"OK"
)
|
update()方法對於任何結果集(QuerySet)均有效,你能夠同時更新多條記錄update()方法會返回一個整型數值,表示受影響的記錄條數。git
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#app01.views.py
from
django.shortcuts
import
render,HttpResponse
from
app01.models
import
Book
def
index(request):
# ==================================修改表紀錄 =================================
# update : 調用者: queryset對象
#方式1
book_obj
=
Book.objects.get(pk
=
1
)
book_obj.title
=
'新值'
book_obj.save()
#方式2
ret
=
Book.objects.
filter
(title
=
"php2"
).update(title
=
"php"
)
return
HttpResponse(
"OK"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#app01.views.py
from
django.shortcuts
import
render,HttpResponse
from
app01.models
import
Book
def
index(request):
# ================================== 查詢表記錄API ==================================
#(1) all方法: 返回值一個queryset對象 ## 查詢全部結果
#book_list=Book.objects.all()
#print(book_list) # [obj1,obj2,.....]
# for obj in book_list:
# print(obj.title,obj.price)
#print(book_list[1].title)
#(2) first,last : 調用者:queryset對象 返回值:model對象 ## first:返回第一條記錄 last:返回最後一條記錄
#book=Book.objects.all().first()
#book=Book.objects.all()[0]
#(3) filter() 返回值:queryset對象 ## 它包含了與所給篩選條件相匹配的對象
# book_list=Book.objects.filter(price=100) # [obj1,obj2,....]
# print(book_list) #<QuerySet [<Book: python>, <Book: php>]>
# book_obj=Book.objects.filter(price=100).first()
# ret=Book.objects.filter(title="go",price=200)
# print(ret)
#(4) get() 有且只有一個查詢結果時纔有意義 返回值:model對象 ## 若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
# book_obj=Book.objects.get(title="go")
# book_obj=Book.objects.get(price=100)
# print(book_obj.price)
# (5) exclude 返回值:queryset對象 ##它包含了與所給篩選條件不匹配的對象 與filter() 相反
# ret=Book.objects.exclude(title="go")
# print(ret)
# (6) order_by 調用者: queryset對象 返回值: queryset對象 ## 對查詢結果排序
# ret=Book.objects.all().order_by("-id")
# ret=Book.objects.all().order_by("price","id")
# print(ret)
# (7) count() 調用者: queryset對象 返回值: int ##返回數據庫中匹配查詢(QuerySet)的對象數量。
# ret=Book.objects.all().count()
# print(ret)
# (8) exist() ##若是QuerySet包含數據,就返回True,不然返回False
# ret=Book.objects.all().exists()
#
# if ret:
# print("ok")
# (9) values 方法 調用者: queryset對象 返回值:queryset對象
# ret=Book.objects.all()
# for i in ret:
# print(i.title)
# ret=Book.objects.all().values("price","title")
# print(ret)
'''
values:
temp=[]
for obj in Book.objects.all()
temp.append({
"price"=obj.price
"title"=obj.title
})
return temp
'''
# <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('100.00')}, {'price': Decimal('200.00')}]>
#print(ret[0].get("price")) # 100.00
# (10) values_list 方法 調用者: queryset對象 返回值:queryset對象
# ret=Book.objects.all().values_list("price","title")
# # print(ret) #<QuerySet [(Decimal('100.00'),), (Decimal('100.00'),), (Decimal('200.00'),)]>
# print(ret)
'''
values:
<QuerySet [{'title': 'python紅寶書', 'price': Decimal('100.00')}, {'title': 'php', 'price': Decimal('100.00')}, {'title': 'go', 'price': Decimal('200.00')}]>
values_list:
<QuerySet [(Decimal('100.00'), 'python紅寶書'), (Decimal('100.00'), 'php'), (Decimal('200.00'), 'go')]>
'''
# 11 distinct ##從返回結果中剔除重複紀錄 reverse對查詢結果反向排序
# ret=Book.objects.all().distinct() #沒有意義
# ret=Book.objects.all().values("price").distinct()
#Book.objects.all().filter().order_by().filter().reverse().first()
# ================================== 基於雙下劃線的模糊查詢 ==================================
# ret=Book.objects.filter(price__gt=10,price__lt=200)
# ret=Book.objects.filter(title__startswith="p")
#ret=Book.objects.filter(title__contains="h")
#ret=Book.objects.filter(title__icontains="h") #忽略大小寫
#ret=Book.objects.filter(price__in=[100,200,300])
#ret=Book.objects.filter(price__range=[200,300])
#ret=Book.objects.filter(pub_date__year=2018,pub_date__month=5)
return
HttpResponse(
"OK"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# app01.models.py
from
django.db
import
models
class
Emp(models.Model):
name
=
models.CharField(max_length
=
32
)
age
=
models.IntegerField()
salary
=
models.DecimalField(max_digits
=
8
, decimal_places
=
2
)
dep
=
models.CharField(max_length
=
32
)
province
=
models.CharField(max_length
=
32
)
# app01.views.py
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
from
django.db.models
import
Avg,
Max
,
Min
, Count
def
query(request):
# -------------------------單表 聚合與分組查詢---------------------------
# ------------------------->聚合 aggregate:返回值是一個字典,再也不是queryset
# 查詢全部書籍的平均價格
ret
=
Book.objects.
all
().aggregate(avg_price
=
Avg(
"price"
), max_price
=
Max
(
"price"
))
print
(ret)
# {'avg_price': 151.0, 'max_price': Decimal('301.00')}
ret
=
Book.objects.aggregate(Avg(
'price'
),
Max
(
'price'
),
Min
(
'price'
))
print
(ret)
# {'price__avg': 151.0, 'price__max': Decimal('301.00'), 'price__min': Decimal('12.99')}
# ------------------------->分組查詢 annotate ,返回值依然是queryset
# 單表分組查詢的ORM語法: 單表模型.objects.values("group by的字段").annotate(聚合函數("統計字段"))
# 在單表分組下, 按着主鍵進行group by是沒有任何意義的.
# 查詢每個部門的名稱以及員工的平均薪水
# select dep,Avg(salary) from emp group by dep
ret
=
Emp.objects.values(
"dep"
).annotate(avg_salary
=
Avg(
"salary"
))
print
(ret)
# <QuerySet [{'avg_salary': 5000.0, 'dep': '保安部'}, {'avg_salary': 51000.0, 'dep': '教學部'}]>
# 查詢每個省份的名稱以及員工數
ret
=
Emp.objects.values(
"province"
).annotate(c
=
Count(
"id"
))
print
(ret)
# <QuerySet [{'province': '山東省', 'c': 2}, {'province': '河北省', 'c': 1}]>
# 補充知識點:
# ret=Emp.objects.all()
# print(ret) # select * from emp
# ret=Emp.objects.values("name")
# print(ret) # select name from emp
return
HttpResponse(
'OK'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
from
django.db
import
models
# Create your models here.
from
django.db
import
models
'''
Book ---- Publish 一對多
'''
class
Author(models.Model):
nid
=
models.AutoField(primary_key
=
True
)
name
=
models.CharField( max_length
=
32
)
age
=
models.IntegerField()
# 一對一
authordetail
=
models.OneToOneField(to
=
"AuthorDetail"
,to_field
=
"nid"
,on_delete
=
models.CASCADE)
def
__str__(
self
):
return
self
.name
# 做者詳情表
class
AuthorDetail(models.Model):
nid
=
models.AutoField(primary_key
=
True
)
birthday
=
models.DateField()
telephone
=
models.BigIntegerField()
addr
=
models.CharField( max_length
=
64
)
# 出版社表
class
Publish(models.Model):
nid
=
models.AutoField(primary_key
=
True
)
name
=
models.CharField( max_length
=
32
)
city
=
models.CharField( max_length
=
32
)
email
=
models.EmailField()
def
__str__(
self
):
return
self
.name
class
Book(models.Model):
nid
=
models.AutoField(primary_key
=
True
)
title
=
models.CharField( max_length
=
32
)
publishDate
=
models.DateField()
price
=
models.DecimalField(max_digits
=
5
,decimal_places
=
2
)
# 一對多關係
publish
=
models.ForeignKey(to
=
"Publish"
,to_field
=
"nid"
,on_delete
=
models.CASCADE,)
'''
publish_id INT ,
FOREIGN KEY (publish_id) REFERENCES publish(id)
'''
#多對多
authors
=
models.ManyToManyField(to
=
"Author"
)
'''
CREATE TABLE book_authors(
id INT PRIMARY KEY auto_increment ,
book_id INT ,
author_id INT ,
FOREIGN KEY (book_id) REFERENCES book(id),
FOREIGN KEY (author_id) REFERENCES author(id)
)
'''
# class Book2Author(models.Model):
#
# nid = models.AutoField(primary_key=True)
# book=models.ForeignKey(to="Book")
# author=models.ForeignKey(to="Author")
def
__str__(
self
):
return
self
.title
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
def
add(request):
# -------------------------一對多的關係-------------------------
#方式1:
#爲book表綁定出版社: book --- publish
book_obj
=
Book.objects.create(title
=
"紅樓夢"
,price
=
100
,publishDate
=
"2012-12-12"
,publish_id
=
1
)
print
(book_obj.title)
#方式2:
#pub_obj = Publish.objects.get(nid=1)
pub_obj
=
Publish.objects.
filter
(nid
=
1
).first()
book_obj
=
Book.objects.create(title
=
"三國演繹"
,price
=
100
,publishDate
=
"2012-12-12"
,publish
=
pub_obj)
print
(book_obj.publish)
# 與這本書籍關聯的出版社對象
print
(book_obj.publish_id)
# -------------------------多對多的關係-------------------------
book_obj
=
Book.objects.create(title
=
"python全棧開發"
,price
=
100
,publishDate
=
"2012-12-12"
,publish_id
=
1
)
egon
=
Author.objects.get(name
=
"egon"
)
alex
=
Author.objects.get(name
=
"alex"
)
#綁定多對多關係的API
book_obj.authors.add(egon,alex)
book_obj.authors.add(
1
,
2
,
3
)
book_obj.authors.add(
*
[
1
,
2
,
3
])
#解除多對多關係
book_obj
=
Book.objects.
filter
(nid
=
4
).first()
book_obj.authors.remove(
2
)
#book_obj.authors.remove(*[1,2]) # 將某個特定的對象從被關聯對象集合中去除。
book_obj.authors.clear()
# 清空被關聯對象集合
book_obj.authors.
set
()
# 先清空再設置
return
HttpResponse(
"OK"
)
|
1
2
3
|
def
delete_book(request,delete_book_id):
Book.objects.
filter
(pk
=
delete_book_id).delete()
return
redirect(
"/books/"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
def
change_book(request,edit_book_id):
edit_book_obj
=
Book.objects.
filter
(pk
=
edit_book_id).first()
if
request.method
=
=
"POST"
:
title
=
request.POST.get(
"title"
)
price
=
request.POST.get(
"price"
)
pub_date
=
request.POST.get(
"pub_date"
)
# 多對一
publish_id
=
request.POST.get(
"publish_id"
)
#多對多
authors_id_list
=
request.POST.getlist(
"authors_id_list"
)
# checkbox,select
Book.objects.
filter
(pk
=
edit_book_id).update(title
=
title,price
=
price,publishDate
=
pub_date,publish_id
=
publish_id)
# edit_book_obj.authors.clear()
# edit_book_obj.authors.add(*authors_id_list)
#多對多
edit_book_obj.authors.
set
(authors_id_list)
return
redirect(
"/books/"
)
publish_list
=
Publish.objects.
all
()
author_list
=
Author.objects.
all
()
return
render(request,
"editbook.html"
,{
"edit_book_obj"
:edit_book_obj,
"publish_list"
:publish_list,
"author_list"
:author_list})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
A
-
B
關聯屬性在A表中
正向查詢: A
-
-
-
-
-
-
>B
反向查詢: B
-
-
-
-
-
-
>A
基於對象的跨表查詢(子查詢)
# 一對多查詢
正向查詢:按字段
反向查詢:表名小寫_set.
all
()
book_obj.publish
Book(關聯屬性:publish)對象
-
-
-
-
-
-
-
-
-
-
-
-
-
-
> Publish對象
<
-
-
-
-
-
-
-
-
-
-
-
-
-
-
publish_obj.book_set.
all
()
# queryset
# 多對多查詢
正向查詢:按字段
反向查詢:表名小寫_set.
all
()
book_obj.authors.
all
()
Book(關聯屬性:authors)對象
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
> Author對象
<
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
author_obj.book_set.
all
()
# queryset
# 一對一查詢
正向查詢:按字段
反向查詢:表名小寫
author.authordetail
Author(關聯屬性:authordetail)對象
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
>AuthorDetail對象
<
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
authordetail.author
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
def
query(request):
# -------------------------基於對象的跨表查詢(子查詢)-----------------------
# 一對多查詢的正向查詢 : 查詢python全棧開發這本書的出版社的名字
book_obj
=
Book.objects.
filter
(title
=
"python全棧開發"
).first()
print
(book_obj.publish)
# 與這本書關聯的出版社對象
print
(book_obj.publish.name)
# 一對多查詢的反向查詢 : 查詢人民出版社出版過的書籍名稱
publish
=
Publish.objects.
filter
(name
=
"人民出版社"
).first()
ret
=
publish.book_set.
all
()
print
(ret)
# 多對多查詢的正向查詢 : 查詢python全棧開發這本書的全部做者的名字
book_obj
=
Book.objects.
filter
(title
=
"python全棧開發"
).first()
author_list
=
book_obj.authors.
all
()
# queryset對象 [author_obj1,...]
for
author
in
author_list:
print
(author.name)
# 多對多查詢的反向查詢 : 查詢alex出版過的全部書籍名稱
alex
=
Author.objects.
filter
(name
=
"alex"
).first()
book_list
=
alex.book_set.
all
()
for
book
in
book_list:
print
(book.title)
# 一對一查詢的正向查詢 : 查詢alex的手機號
alex
=
Author.objects.
filter
(name
=
"alex"
).first()
print
(alex.authordetail.telephone)
# 一對一查詢的反向查詢 : 查詢手機號爲110的做者的名字和年齡
ad
=
AuthorDetail.objects.
filter
(telephone
=
"110"
).first()
print
(ad.author.name)
print
(ad.author.age)
return
HttpResponse(
"ok"
)
|
1
2
3
4
5
6
7
8
|
A
-
B
關聯屬性在A表中
正向查詢: A
-
-
-
-
-
-
>B
反向查詢: B
-
-
-
-
-
-
>A
基於雙下劃線的跨表查詢(join查詢)
key:正向查詢按字段,反向查詢按表名小寫
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
def
query(request):
# -------------------------基於雙下劃線的跨表查詢(join查詢)-----------------------
'''
正向查詢按字段,反向查詢按表名小寫用來告訴ORM引擎join哪張表
'''
# 一對多查詢 : 查詢python全棧開發這本書的出版社的名字
# 方式1:
ret
=
Book.objects.
filter
(title
=
"python全棧開發"
).values(
"publish__name"
)
print
(ret)
# <QuerySet [{'publish__name': '南京出版社'}]>
# 方式2:
ret
=
Publish.objects.
filter
(book__title
=
"python全棧開發"
).values(
"name"
)
print
(ret)
# 多對多查詢 : 查詢python全棧開發這本書的全部做者的名字
# 方式1:
# 需求: 經過Book表join與其關聯的Author表,屬於正向查詢:按字段authors通知ORM引擎join book_authors與author
ret
=
Book.objects.
filter
(title
=
"python全棧開發"
).values(
"authors__name"
)
print
(ret)
# <QuerySet [{'authors__name': 'alex'}, {'authors__name': 'egon'}]>
# 方式2:
# 需求: 經過Author表join與其關聯的Book表,屬於反向查詢:按表名小寫book通知ORM引擎join book_authors與book表
ret
=
Author.objects.
filter
(book__title
=
"python全棧開發"
).values(
"name"
)
print
(ret)
# <QuerySet [{'name': 'alex'}, {'name': 'egon'}]>
# 一對一查詢的查詢 : 查詢alex的手機號
# 方式1:
# 需求: 經過Author表join與其關聯的AuthorDetail表,屬於正向查詢:按字段authordetail通知ORM引擎join Authordetail表
ret
=
Author.objects.
filter
(name
=
"alex"
).values(
"authordetail__telephone"
)
print
(ret)
# <QuerySet [{'authordetail__telephone': 110}]>
# 方式2:
# 需求: 經過AuthorDetail表join與其關聯的Author表,屬於反向查詢:按表名小寫author通知ORM引擎join Author表
ret
=
AuthorDetail.objects.
filter
(author__name
=
"alex"
).values(
"telephone"
)
print
(ret)
# <QuerySet [{'telephone': 110}]>
# 進階練習:(連續跨表)
# 練習: 手機號以110開頭的做者出版過的全部書籍名稱以及書籍出版社名稱
# 方式1:
# 需求: 經過Book表join AuthorDetail表, Book與AuthorDetail無關聯,因此必需連續跨表
ret
=
Book.objects.
filter
(authors__authordetail__telephone__startswith
=
"110"
).values(
"title"
,
"publish__name"
)
print
(ret)
# 方式2:
ret
=
Author.objects.
filter
(authordetail__telephone__startswith
=
"110"
).values(
"book__title"
,
"book__publish__name"
)
print
(ret)
return
HttpResponse(
"OK"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
def
query(request):
# ------------------------->聚合 aggregate:返回值是一個字典,再也不是queryset
# 查詢全部書籍的平均價格
from
django.db.models
import
Avg,
Max
,
Min
, Count
ret
=
Book.objects.
all
().aggregate(avg_price
=
Avg(
"price"
), max_price
=
Max
(
"price"
))
print
(ret)
# {'avg_price': 151.0, 'max_price': Decimal('301.00')}
ret
=
Book.objects.aggregate(Avg(
'price'
),
Max
(
'price'
),
Min
(
'price'
))
print
(ret)
# {'price__avg': 151.0, 'price__max': Decimal('301.00'), 'price__min': Decimal('12.99')}
# ------------------------->多表分組查詢 annotate ,返回值依然是queryset
# 單表總結: objects.values("group by的字段").annotate(聚合函數("統計字段"))
# 多表總結:跨表的分組查詢的模型:
# 方式1:每個後的表模型.objects.values("pk").annotate(聚合函數(關聯表__統計字段)).values("表模型的全部字段以及統計字段")
# 方式2:每個後的表模型.objects.annotate(聚合函數(關聯表__統計字段)).values("表模型的全部字段以及統計字段")
#################### 方式1: 跨表分組查詢####################
#查詢每個出版社的名稱以及出版的書籍個數
#法1:
ret
=
Publish.objects.values(
"name"
).annotate(c
=
Count(
"book__title"
))
print
(ret)
# <QuerySet [{'name': '人民出版社', 'c': 3}, {'name': '南京出版社', 'c': 1}]>
ret
=
Publish.objects.values(
"nid"
).annotate(c
=
Count(
"book__title"
))
print
(ret)
# <QuerySet [{'nid': 1, 'c': 3}, {'nid': 2, 'c': 1}]>
# 法2:
ret
=
Publish.objects.values(
"nid"
).annotate(c
=
Count(
"book__title"
)).values(
"name"
,
"c"
)
print
(ret)
# <QuerySet [{'name': '人民出版社', 'c': 3}, {'name': '南京出版社', 'c': 1}]>
#查詢每個做者的名字以及出版過的書籍的最高價格
ret
=
Author.objects.values(
"pk"
).annotate(max_price
=
Max
(
"book__price"
)).values(
"name"
,
"max_price"
)
print
(ret)
#查詢每個書籍的名稱以及對應的做者個數
ret
=
Book.objects.values(
"pk"
).annotate(c
=
Count(
"authors__name"
)).values(
"title"
,
"c"
)
print
(ret)
#################### 方式2: 跨表分組查詢####################
# 示例1 查詢每個出版社的名稱以及出版的書籍個數
# ret=Publish.objects.values("nid").annotate(c=Count("book__title")).values("name","email","c")
# ret=Publish.objects.all().annotate(c=Count("book__title")).values("name","c","city")
ret
=
Publish.objects.annotate(c
=
Count(
"book__title"
)).values(
"name"
,
"c"
,
"city"
)
print
(ret)
##################### 練習 ####################
# 統計每一本以py開頭的書籍的做者個數:
# 每個後的表模型.objects.values("pk").annotate(聚合函數(關聯表__統計字段)).values("表模型的全部字段以及統計字段")
ret
=
Book.objects.
filter
(title__startswith
=
"py"
).values(
"pk"
).annotate(c
=
Count(
"authors__name"
)).values(
"title"
,
"c"
)
# 統計不止一個做者的圖書
ret
=
Book.objects.values(
"pk"
).annotate(c
=
Count(
"authors__name"
)).
filter
(c__gt
=
1
).values(
"title"
,
"c"
)
print
(ret)
#根據一本圖書做者數量的多少對查詢集 QuerySet進行排序:
ret
=
Book.objects.annotate(num_authors
=
Count(
'authors'
)).order_by(
'num_authors'
)
return
HttpResponse(
"查詢成功"
)
|
使用F表達式引用模型的字段sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
from
django.shortcuts
import
render, HttpResponse
from
app01.models
import
*
from
django.db.models
import
F,Q
def
query(request):
#################### F查詢####################
#兩個字段的值作比較, F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。
# 查詢評論數大於收藏數的書籍
Book.objects.
filter
(commnetNum__lt
=
F(
'keepNum'
))
# 查詢評論數大於收藏數2倍的書籍
Book.objects.
filter
(commnetNum__lt
=
F(
'keepNum'
)
*
2
)
#修改操做也可使用F函數,好比將每一本書的價格提升30元:
Book.objects.
all
().update(price
=
F(
"price"
)
+
30
)
####################Q查詢####################
#filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR 語句),你可使用Q 對象。
#Q對象可使用& 和| 操做符組合起來。當一個操做符在兩個Q 對象上使用時,它產生一個新的Q 對象。
bookList
=
Book.objects.
filter
(Q(authors__name
=
"yuan"
) | Q(authors__name
=
"egon"
))
#sql ...WHERE name ="yuan" OR name ="egon"
#Q對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢:
bookList
=
Book.objects.
filter
(Q(authors__name
=
"yuan"
) & ~Q(publishDate__year
=
2017
)).values_list(
"title"
)
#混合使用Q對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。
bookList
=
Book.objects.
filter
(Q(publishDate__year
=
2016
) | Q(publishDate__year
=
2017
),
title__icontains
=
"python"
)
return
HttpResponse(
"查詢成功"
)
|
有些狀況下,Django的查詢語法難以簡單的表達複雜的 WHERE 子句,對於這種狀況, Django 提供了 extra() QuerySet修改機制 它能在 QuerySet生成的SQL從句中注入新子句,extra能夠指定一個或多個 參數,例如 select, where or tables.這些參數都不是必須的,可是你至少要使用一個!要注意這些額外的方式對不一樣的數據庫引擎可能存在移植性問題.(由於你在顯式的書寫SQL語句),除非萬不得已,儘可能避免這樣作.數據庫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# 每個後的表模型.objects.values("pk").annotate(聚合函數(關聯表__統計字段)).values("表模型的全部字段以及統計字段")
# 查詢每個分類名稱以及對應的文章數
ret
=
models.Category.objects.values(
"pk"
).annotate(c
=
Count(
"article__title"
)).values(
"title"
,
"c"
)
# 查詢當前站點的每個分類名稱以及對應的文章數
cate_list
=
models.Category.objects.
filter
(blog
=
blog).values(
"pk"
).annotate(c
=
Count(
"article__title"
)).values_list(
"title"
,
"c"
)
# 查詢當前站點的每個標籤名稱以及對應的文章數
tag_list
=
models.Tag.objects.
filter
(blog
=
blog).values(
"pk"
).annotate(c
=
Count(
"article"
)).values_list(
"title"
,
"c"
)
# 查詢當前站點每個年月的名稱以及對應的文章數
"""
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
參數之select
The select 參數可讓你在 SELECT 從句中添加其餘字段信息,它應該是一個字典,存放着屬性名到 SQL 從句的映射。
queryResult=models.Article
.objects.extra(select={'is_recent': "create_time > '2017-09-05'"})
結果集中每一個 Entry 對象都有一個額外的屬性is_recent, 它是一個布爾值,表示 Article對象的create_time 是否晚於2017-09-05.
"""
ret
=
models.Article.objects.extra(select
=
{
"is_recent"
:
"create_time > '2018-09-05'"
}).values(
"title"
,
"is_recent"
)
# 方式1:
# mysql
date_list
=
models.Article.objects.
filter
(user
=
user).extra(select
=
{
"y_m_date"
:
"date_format(create_time,'%%Y/%%m')"
}
).values(
"y_m_date"
).annotate(c
=
Count(
"nid"
)).values_list(
"y_m_date"
,
"c"
)
# sqlite
date_list
=
models.Article.objects.
filter
(user
=
user).extra(select
=
{
"y_m_date"
:
"strftime('%%Y/%%m',create_time)"
}
).values(
"y_m_date"
).annotate(c
=
Count(
"nid"
)).values_list(
"y_m_date"
,
"c"
)
# 方式2:
from
django.db.models.functions
import
TruncMonth
ret
=
models.Article.objects.
filter
(user
=
user).annotate(month
=
TruncMonth(
"create_time"
)).values(
"month"
).annotate(c
=
Count(
"nid"
)).values_list(
"month"
,
"c"
)
# 日期歸檔查詢的方式2
from
django.db.models.functions
import
TruncMonth
"""
Sales.objects
.annotate(month=TruncMonth('timestamp')) # Truncate to month and add to select list
.values('month') # Group By month
.annotate(c=Count('id')) # Select the count of the grouping
.values('month', 'c') # (might be redundant, haven't tested) select month and count
"""
"""
參數之where
"""
val
=
"2018-10"
# mysql
all_count
=
models.Article.objects.
filter
(blog
=
blog).extra(
where
=
[
'date_format(create_time,"%%Y-%%m")=%s'
], params
=
[val, ]).count()
article_list
=
models.Article.objects.
filter
(blog
=
blog).extra(
where
=
[
'date_format(create_time,"%%Y-%%m")=%s'
], params
=
[val, ])[page_info.start():page_info.end()]
# sqlite
all_count
=
models.Article.objects.
filter
(blog
=
blog).extra(
where
=
[
'strftime("%%Y-%%m",create_time)=%s'
], params
=
[val, ]).count()
article_list
=
models.Article.objects.
filter
(blog
=
blog).extra(
where
=
[
'strftime("%%Y-%%m",create_time)=%s'
], params
=
[val, ])[page_info.start():page_info.end()]
#直接寫sql語句
# mysql
cursor
=
connection.cursor()
sql
=
'select count(1) as nm,date_format(create_time,"%%Y-%%m") as ctime from article where blog_id= %s group by date_format(create_time,"%%Y-%%m")'
cursor.execute(sql,(blog.nid,))
date_list
=
cursor.fetchall()
# sqlite
date_list
=
models.Article.objects.raw(
'select nid, count(1) as num,strftime("%Y-%m",create_time) as ctime from article group by strftime("%Y-%m",create_time)'
)
|
主鍵的快捷查詢方式:pkdjango
from django.db import models # from django.contrib.auth.models import AbstractUser # class UserInfo(AbstractUser): # """ # 用戶信息 # """ # nid = models.AutoField(primary_key=True) # telephone = models.CharField(max_length=11, null=True, unique=True) # avatar = models.FileField(upload_to='avatars/', default="avatars/default.png") # create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) # # blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) # # def __str__(self): # return self.username # # class Meta: # verbose_name = '我的博客信息' # verbose_name_plural = '博客信息' class UserInfo(models.Model): """ 用戶表 """ nid = models.BigAutoField(primary_key=True) username = models.CharField(verbose_name='用戶名', max_length=32, unique=True) password = models.CharField(verbose_name='密碼', max_length=64) nickname = models.CharField(verbose_name='暱稱', max_length=32) email = models.EmailField(verbose_name='郵箱', unique=True) avatar = models.FileField(verbose_name='頭像',upload_to='avatars/', default="avatars/default.png") # 被傳到`MEDIA_ROOT/uploads/2015/01/30`目錄,增長了一個時間劃分 # avatar = models.FileField(upload_to='uploads/%Y/%m/%d/') create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) fans = models.ManyToManyField(verbose_name='粉絲們', to='UserInfo', through='UserFans', related_name='f', through_fields=('user', 'follower')) class Meta: verbose_name = '我的博客信息' verbose_name_plural = '博客信息' class Blog(models.Model): """ 博客信息 """ nid = models.BigAutoField(primary_key=True) title = models.CharField(verbose_name='我的博客標題', max_length=64) site = models.CharField(verbose_name='站點名稱', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主題', max_length=32) user = models.OneToOneField(to='UserInfo', to_field='nid',on_delete=models.CASCADE) theme_choices = [ ('default', "默認主題"), ('bule', "藍色主題"), ('red', "紅色主題"), ] def __str__(self): return self.title class Meta: verbose_name = '我的博客信息' verbose_name_plural = '博客信息' class UserFans(models.Model): """ 互粉關係表 """ user = models.ForeignKey( verbose_name='博主', to='UserInfo', to_field='nid', related_name='users',on_delete=models.CASCADE ) follower = models.ForeignKey( verbose_name='粉絲', to='UserInfo', to_field='nid', related_name='followers',on_delete=models.CASCADE ) class Meta: verbose_name = '互粉關係' verbose_name_plural = '互粉關係' unique_together = [ ('user', 'follower'), ] class Category(models.Model): """ 博主我的文章分類表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分類標題', max_length=32) parent = models.ForeignKey(verbose_name='父ID', to='Category', to_field='nid', on_delete=models.CASCADE, null=True) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid',on_delete=models.CASCADE) class Meta: verbose_name = '文章分類' verbose_name_plural = '文章分類' class ArticleDetail(models.Model): """ 文章詳細表 """ content = models.TextField(verbose_name='文章內容', ) article = models.OneToOneField(verbose_name='所屬文章', to='Article', to_field='nid',on_delete=models.CASCADE) class Meta: verbose_name = '文章詳細' verbose_name_plural = '文章詳細' class UpDown(models.Model): """ 文章頂或踩 """ article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid',on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='贊或踩用戶', to='UserInfo', to_field='nid',on_delete=models.CASCADE) up = models.BooleanField(verbose_name='是否贊') class Meta: verbose_name = '文章頂踩' verbose_name_plural = '文章頂踩' unique_together = [ ('article', 'user'), ] class Comment(models.Model): """ 評論表 """ nid = models.BigAutoField(primary_key=True) content = models.CharField(verbose_name='評論內容', max_length=255) create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) reply = models.ForeignKey(verbose_name='回覆評論', to='self', related_name='back', null=True,on_delete=models.CASCADE) article = models.ForeignKey(verbose_name='評論文章', to='Article', to_field='nid',on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='評論者', to='UserInfo', to_field='nid',on_delete=models.CASCADE) class Meta: verbose_name = '文章評論' verbose_name_plural = '文章評論' class Tag(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='標籤名稱', max_length=32) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid',on_delete=models.CASCADE) class Meta: verbose_name = '文章標籤' verbose_name_plural = '文章標籤' class Article(models.Model): nid = models.BigAutoField(primary_key=True) title = models.CharField(verbose_name='文章標題', max_length=128) summary = models.CharField(verbose_name='文章簡介', max_length=255) read_count = models.IntegerField(default=0) comment_count = models.IntegerField(default=0) up_count = models.IntegerField(default=0) down_count = models.IntegerField(default=0) create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid',on_delete=models.CASCADE) category = models.ForeignKey(verbose_name='文章類型', to='Category', to_field='nid', null=True,on_delete=models.CASCADE) type_choices = [ (1, "編程語言"), (2, "操做系統"), (3, "Web前端"), (4, "數據庫"), (5, "English"), (6, "其餘分類"), ] article_type_id = models.IntegerField(choices=type_choices, default=None) tags = models.ManyToManyField( to="Tag", through='Article2Tag', through_fields=('article', 'tag'), ) class Meta: verbose_name = '文章信息' verbose_name_plural = '文章信息' class Article2Tag(models.Model): article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid',on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='標籤', to="Tag", to_field='nid',on_delete=models.CASCADE) class Meta: verbose_name = '文章與標籤' verbose_name_plural = '文章與標籤' unique_together = [ ('article', 'tag'), ] class Tpl(models.Model): user = models.ForeignKey(UserInfo, on_delete=models.CASCADE) title = models.CharField(max_length=32) content = models.TextField() class Trouble(models.Model): title = models.CharField(max_length=32) detail = models.TextField() user = models.ForeignKey(UserInfo,related_name='u',on_delete=models.CASCADE) # ctime = models.CharField(max_length=32) # 1491527007.452494 ctime = models.DateTimeField() status_choices = ( (1,'未處理'), (2,'處理中'), (3,'已處理'), ) status = models.IntegerField(choices=status_choices,default=1) processer = models.ForeignKey(UserInfo,related_name='p',null=True,blank=True,on_delete=models.CASCADE) solution = models.TextField(null=True) ptime = models.DateTimeField(null=True) pj_choices = ( (1, '不滿意'), (2, '通常'), (3, '很滿意'), ) pj = models.IntegerField(choices=pj_choices,null=True,default=2) """ form中: from django.forms import fields theme = fields.ChoiceField( choices=models.Blog.theme_choices, widget=widgets.Select(attrs={'class': 'form-control'}) ) 模板中: {{ form.theme }} models中: status_choices = ( (1,'未處理'), (2,'處理中'), (3,'已處理'), ) status = models.IntegerField(choices=status_choices,default=1) ptime = models.DateTimeField(null=True,blank=True) views中: dic['ptime'] = datetime.datetime.now() 模板中: {% for row in result %} <td>{{ row.get_status_display }}</td> {% endfor %} models中: type_choices = [ (1, "編程語言"), (2, "操做系統"), (3, "Web前端"), (4, "數據庫"), (5, "English"), (6, "其餘分類"), ] views: article_type_list = models.Article.type_choices """
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_contenttype.settings") import django django.setup() from app01.models import Post, Picture, Comment from django.contrib.auth.models import User # 準備測試數據 user_1 = User.objects.create_user(username='aaa', password='123') user_2 = User.objects.create_user(username='bbb', password='123') user_3 = User.objects.create_user(username='ccc', password='123') post_1 = Post.objects.create(author=user_1, title='Python入門教程') post_2 = Post.objects.create(author=user_2, title='Python進階教程') post_3 = Post.objects.create(author=user_1, title='Python入土教程') picture_1 = Picture.objects.create(author=user_1, image='小姐姐01.jpg') picture_2 = Picture.objects.create(author=user_1, image='小姐姐02.jpg') picture_3 = Picture.objects.create(author=user_3, image='小哥哥01.jpg') # 給帖子建立評論數據 comment_1 = Comment.objects.create(author=user_1, content='好文!', content_object=post_1) # 給圖片建立評論數據 comment_2 = Comment.objects.create(author=user_2, content='好美!', content_object=picture_1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
<!--查看全部 views.py 傳過來的book_list book_list=Book.objects.all()-->
<
tbody
>
{% for book in book_list %}
<
tr
>
<
td
>{{ forloop.counter }}</
td
>
<
td
>{{ book.title }}</
td
>
<
td
>{{ book.price }}</
td
>
<
td
>{{ book.publishDate|date:"Y-m-d" }}</
td
>
<
td
>
{{ book.publish.name }}
</
td
>
<
td
>
{% for author in book.authors.all %}
{% if forloop.last %}
<
span
>{{ author.name }}</
span
>
{% else %}
<
span
>{{ author.name }}</
span
>,
{% endif %}
{% endfor %}
</
td
>
<
td
>
<
a
href="/books/{{ book.pk }}/change/" class="btn btn-warning">編輯</
a
>
<
a
href="/books/{{ book.pk }}/delete/" class="btn btn-danger">刪除</
a
>
</
td
>
</
tr
>
{% endfor %}
</
tbody
>
<!--編輯 views.py 傳過來的edit_book_obj publish_list=Publish.objects.all() author_list=Author.objects.all()-->
<
form
action="" method="post">
{% csrf_token %}
<
div
class="form-group">
<
label
for="">名稱</
label
>
<
input
type="text" name="title" class="form-control" value="{{ edit_book_obj.title }}">
</
div
>
<
div
class="form-group">
<
label
for="">價格</
label
>
<
input
type="text" name="price" class="form-control" value="{{ edit_book_obj.price }}">
</
div
>
<
div
class="form-group">
<
label
for="">出版日期</
label
>
<
input
type="date" name="pub_date" class="form-control"
value="{{ edit_book_obj.publishDate|date:'Y-m-d' }}">
</
div
>
<
div
class="form-group">
<
label
for="">出版社</
label
>
<
select
name="publish_id" id="" class="form-control">
{% for publish in publish_list %}
{% if edit_book_obj.publish == publish %}
<
option
selected value="{{ publish.pk }}">{{ publish.name }}</
option
>
{% else %}
<
option
value="{{ publish.pk }}">{{ publish.name }}</
option
>
{% endif %}
{% endfor %}
</
select
>
</
div
>
<
div
class="form-group">
<
label
for="">做者</
label
>
<
select
type="text" name="authors_id_list" multiple class="form-control">
{% for author in author_list %}
{% if author in edit_book_obj.authors.all %}
<
option
selected value="{{ author.pk }}">{{ author.name }}</
option
>
{% else %}
<
option
value="{{ author.pk }}">{{ author.name }}</
option
>
{% endif %}
{% endfor %}
</
select
>
</
div
>
<
input
type="submit" class="btn btn-default">
</
form
>
|
方法名 | 解釋 |
---|---|
filter() | 過濾查詢對象。 |
exclude() | 排除知足條件的對象 |
annotate() | 使用聚合函數 |
order_by() | 對查詢集進行排序 |
reverse() | 反向排序 |
distinct() | 對查詢集去重 |
values() | 返回包含對象具體值的字典的QuerySet |
values_list() | 與values()相似,只是返回的是元組而不是字典。 |
dates() | 根據日期獲取查詢集 |
datetimes() | 根據時間獲取查詢集 |
none() | 建立空的查詢集 |
all() | 獲取全部的對象 |
union() | 並集 |
intersection() | 交集 |
difference() | 差集 |
select_related() | 附帶查詢關聯對象 |
prefetch_related() |
預先查詢 |
extra() | 附加SQL查詢 |
defer() | 不加載指定字段 |
only() | 只加載指定的字段 |
using() | 選擇數據庫 |
select_for_update() |
鎖住選擇的對象,直到事務結束。 |
raw() | 接收一個原始的SQL查詢 |
方法名 | 解釋 |
---|---|
get() | 獲取單個對象 |
create() | 建立對象,無需save() |
get_or_create() | 查詢對象,若是沒有找到就新建對象 |
update_or_create() | 更新對象,若是沒有找到就建立對象 |
bulk_create() |
批量建立對象 |
count() | 統計對象的個數 |
in_bulk() |
根據主鍵值的列表,批量返回對象 |
iterator() |
獲取包含對象的迭代器 |
latest() | 獲取最近的對象 |
earliest() | 獲取最先的對象 |
first() | 獲取第一個對象 |
last() | 獲取最後一個對象 |
aggregate() | 聚合操做 |
exists() | 判斷queryset中是否有對象 |
update() | 批量更新對象 |
delete() | 批量刪除對象 |
as_manager() | 獲取管理器 |
字段查詢是指如何指定SQL WHERE子句的內容。它們用做QuerySet的filter(), exclude()和get()方法的關鍵字參數。編程
字段名 | 含義 | 示例 | 等價SQL語句 |
exact | 精確等於 | Comment.objects.filter(id__exact=14) | select * from Comment where id=14 |
iexact | 大小寫不敏感的等於 | Comment.objects.filter(headline__iexact=’I like this’) | select * from Comment where upper(headline)=’I LIKE THIS’ |
contains | 模糊匹配 | Comment.objects.filter(headline__contains=’good’) | select * from Comment where headline like 「%good%」 |
icontains | 不區分大小寫的包含匹配 | ||
in | 包含 | Comment.objects.filter(id__in=[1,5,9]) | select * from Comment where id in (1,5,9) |
gt | 大於 | Comment.objects.filter(n_visits__gt=30) | select * from Comment where n_visits>30 |
gte | 大於等於 | Comment.objects.filter(n_visits__gte=30) | select * from COmment where n_visits>=30 |
lt | 小於 | ||
lte | 小於等於 | ||
startswith | 以…開頭 | Comment.objects.filter(body_text__startswith=」Hello」) | select * from Comment where body_text like ‘Hello%’ |
istartswith | 不區分大小寫從開頭匹配 | ||
endswith | 以…結尾 | ||
iendswith | 不區分大小寫從結尾處匹配 | ||
range | 在…範圍內 | start_date=datetime.date(2015,1,1) end_date=datetime.date(2015.2.1) Comment.objects.filter( pub_date__range=(start_date,end_date) ) |
select * from Comment where pub_date between ‘2015-1-1’ and ‘2015-2-1’ |
date | 日期匹配 | ||
year | 年 | Comment.objects.filter( pub_date__year=2015 ) |
select * from Comment where pub_date between ‘2015-1-1 0:0:0’ and ‘2015-12-31 23:59:59’ |
month | 月 | ||
day | 日 | ||
week | 第幾周 | ||
week_day | 星期幾 | ||
time | 時間 | ||
hour | 小時 | ||
minute | 分鐘 | ||
second | 秒 | ||
search | 1.10中被廢棄 | ||
regex | 區分大小寫的正則匹配 | ||
iregex | 不區分大小寫的正則匹配 | ||
isnull | 是否爲空 | Comment.objects.filter( pub_date__isnull=True ) |
select * from Comment where pub_date is NULL |
filter(**kwargs): 返回符合篩選條件的數據集
exclude(**kwargs): 返回不符合篩選條件的數據集
Comment.objects.filter(pub_date__year=2015)
多個filter和exclude能夠連接在一塊兒查詢
Comment.objects.filter(pub_date__year=2015).exclude(pub_date__month=1).exclude(n_visits__exact=0)
get() :查詢單條記錄,注意沒有查詢到數據的時候會報錯
Comment.objects.get(id_exact=1)
all(): 查詢全部數據
Comment.objects.all() Comment.objects.all()[:10] Comment.objects.all[10:20]
order_by(): 排序
Comment.objects.order_by('headline')