模型和數據庫
模型
各種Model Field類型
- AutoField,自動增長的IntegerField,如果不指定,則默認添加。
- IntegerField/BigIntegerField/PositiveSmallIntegerField/SmallIntegerField:都是類似的,只是數字的范圍不同。
- BinaryField/DecimalField:二進制和十進制。
- BooleanField,如果沒有指定default的話,默認為None
- CharField,**必須**接收另外一個參數 max_length
DateField,使用Python的datetime.date實例表示的日期。
需要注意的是,auto_now用於每次保存對象的時候,自動設置該字段為當前時間;auto_now_add則用於第一次被創建時自動設置該字段為當前時間,這些選項還有default之間相互違背的,所以不要同時使用任意多個。這些選項默認保存的是 django.utils.timezone.datetime 里面的now,所以如果想要進行特殊的保存,需要自己重寫save函數。
FileField,上傳文件,字段的選項不支持primary_key和unique。
需要在settting文件里面,需要添加MEDIA_ROOT用來提供文件上傳的根路徑,而參數upload則提供文件具體的位置。 當你刪除了該model,文件需要你自己手動去刪除。
NullBooleanField,和之前BooleanField不同的是,它除了允許True或者False,還允許Null=True,也就是為null。
TextField,適用於大文本字段,如果設定了max_length屬性,那么其只會對組件進行一個內容顯示的限制,但是不會對數據庫存在限制。
- ForeignKey,對應的是一對多的關系,可以指定關聯刪除-**on_delete=models.CASCADE**,如果要關聯的對象還沒有定義好,可以使用其名字。
- limit_choices_to,可以限制關聯返回的內容。
- related_name,可以讓關聯的對象反查到源對象,如果不想創建反向關聯,則設置為"+"即可。需要注意的是,如果沒有使用該Field,那么想要使用反向關聯,則需要**foo_set**,foo為關聯對象的小寫名稱,如果使用了該Field,則可以直接使用自己定義的名稱。
- related_query_name,和上面的作用類似,同樣可以反向查詢,兩者只需要設置一個即可。
- to_field,指定關聯對象的字段名稱,默認情況下為對方的主鍵。
- db_constraint,控制是否在數據庫中為這個外鍵創建約束,默認為True。
- on_delete,可以實現CASCADE,級聯刪除;PROTECT,防止被引用對象刪除,拋出ProtectedError;SET_NULL,將其設置成null;
- ManyToManyField,對應的是多對多的關系。
OneToOneField,對應的是一對一的關系,其可以直接返回關系另一邊的對象,最主要的用途是作為擴展自另外一個模型的主鍵。比如多表繼承就是利用這樣的原理,通過對子模型添加一個隱式的一對一關聯關系到父親模型實現的。
如果你沒有指定其的related_name參數,那么Django將使用當前模型的小寫名稱作為默認值。 如果訪問相應的對象不存在的話,則會拋出ObjectDoesNotExist的異常。 當設置**parent_link**為True時,??
Model Field Options
- Field.null,注意在CharField或者TextField里避免使用null,因為其存儲的值是空字符串而不是NULL。
- Field.blank,和上面的不同,其限制的是組件,而上面限制的是數據庫。
- Field.choices,由可迭代的二元祖來組成,其中元祖里面第一個元素是存儲在數據中的值,第二個則是元素更加詳細的描述,界面上顯示的是后者。,數據庫存儲的是前者。
- Field.db_column,數據庫中用來表示字段的名稱,如果沒有提供,則默認使用filed的名稱。
- Field.db_index,如果為True,則為該字段創建索引。
- Field.db_tablespace,表空間,如果該字段已經創建了索引,那么數據庫表空間的名稱將作為該字段的索引名。注意,部分數據庫不支持表空間。
- Field.db_default,指定一個默認值,它可以是一個值或者可調用對象,注意的是,其不可以是一個可變對象,因為會指向同一個引用。
- Field.editable,如果為false,則不可編輯,那么admin和其它model則忽略掉這個字段。
- Field.error_messages,能夠重寫默認拋出的錯誤信息。
- Field.help_text,將會作為提示信息顯示在表單中。
- Field.primary_key,這意味着null=False和unique=True,所以一個對象只能擁有一個主鍵。
- Field.unique,當設定為True時,不需要再設定db_index,因為其本身就是一個索引的創建。注意的是,ManyToManyField和OneToOneField和FileField以外的其它類型都可以使用這個字段(????)。
- Field.unique_for_date/Field.unique_for_month/Field.unique_for_year/Field,設置對應的時間是唯一的。
- Field.validators,指定驗證器。
- ForeignKey、ManyToManyField和OneToOneField需要通過Field.verbose_name才能自定義設置字段名,其它均可以每個字段類型都可在第一個參數上自定義設置字段的字段名。
- Field.many_to_many,多對多關系;
- Field.many_to_one,多對一關系,例如ForeignKey;
- Field.one_to_many,一對多關系,例如GenericRelation或者ForeignKey的反向;
- Field.one_to_one,一對一關系;
- Field.related_model,指向字段涉及的模型;
自定義Model Field
Relationships
Many-to-one relationships
Many-to-many relationships
One-to-one relationships
Meta 選項
- abstract,如果聲明為True,則表明這是一個抽象基類。
- app_label,如果定義在application之外,則需要指明它是那個applicaition的,也可以通過其屬性自定義格式。
- base_manager_name,指定managers的名字。
- db_table,指定數據庫表格的名字。
- db_tablespace,指定表格空間,如果數據庫不支持則忽略。
- default_manger_name,指定manager的名字。
- default_related_name,指定反向關聯的模型的名稱,需要注意的是,這個名稱應該是唯一的,建議命名中包含app和model名字以避免沖突,
%(app_label)s和%(model_name)s
。 - get_latest_by,指定model中某個可排序的字段的名稱,這樣當通過managers去調用lates函數的時候會返回根據排序的最新的結果。
- managed,是否指明Django為當前模型創建和刪除數據庫表,True或者False。
order_with_respect_to,通常用在關聯對象上面,指定某個字段,使其在父對象中有序。
設置之后,可以通過get_RELATED_order和set_RELATED_order進行獲取關聯對象的已經拍好序的主鍵列表或者是自定義設置其順序。 我們還可以通過get_next_in_order和get_previous_in_order,可以用於獲取一個生成器。
模型屬性
模型方法
創建對象
模型加載
驗證對象
保存對象
- 發出一個pre-save 信號。 發送一個django.db.models.signals.pre_save 信號,以允許監聽該信號的函數完成一些自定義的動作。
大部分字段不需要預處理 —— 字段的數據將保持原樣。預處理只用於具有特殊行為的字段。例如,如果你的模型具有一個auto_now=True 的DateField,那么預處理階段將修改對象中的數據以確保該日期字段包含當前的時間戳。(我們的文檔還沒有所有具有這種“特殊行為”字段的一個列表。)
准備數據庫數據。 要求每個字段提供的當前值是能夠寫入到數據庫中的類型。
大部分字段不需要數據准備。簡單的數據類型,例如整數和字符串,是可以直接寫入的Python 對象。但是,復雜的數據類型通常需要一些改動。 例如,DateField 字段使用Python 的 datetime 對象來保存數據。數據庫保存的不是datetime 對象,所以該字段的值必須轉換成ISO兼容的日期字符串才能插入到數據庫中。
發出一個post-save 信號。 發送一個django.db.models.signals.post_save 信號,以允許監聽聽信號的函數完成一些自定義的動作。
- 如果對象的主鍵屬性為一個求值為True 的值(例如,非None 值或非空字符串),Django 將執行UPDATE。
- 如果對象的主鍵屬性沒有設置或者UPDATE 沒有更新任何記錄,Django 將執行INSERT。
更新對象
刪除對象
Pickling對象
Model.__str__
Model.__eq__
Model.__hash__
Model.get_absolute_url
其它
模型繼承
- 通常,你只想使用父類來持有一些信息,你不想在每個子模型中都敲一遍。這個類永遠不會單獨使用,所以你要使用抽象基類。
- 如果你繼承一個已經存在的模型且想讓每個模型具有它自己的數據庫表,那么應該使用多表繼承。繼承關系在子model和它的每個父類之間添加一個鏈接,這是通過自動創建的OneToOneField來實現的。
- 最后,如果你只是想改變一個模塊Python 級別的行為,而不用修改模型的字段,你可以使用代理模型。
抽象基類
多表繼承
代表模型
多重模型
查詢
關聯對象參考
獲取對象
鏈式過濾
Entry.objects.filter(headline__startswith='What')
.exclude(pub_date__gte=datetime.date.today())
.filter(pub_date__gte=datetime(2005, 1, 30))
使用get
另外一些查詢字段:
- exact:精確匹配,通常我們查詢時使用的字段都包含了exact,只不過Dangjo都默認幫你處理好了;
- iexact:匹配,忽略大小寫;
- contains,icontains:包含和忽略大小寫的包含;
- startswith,endswith,istartswith,iendswith:以某字符串開頭和其忽略大小寫的情況;
- pk:和主鍵的作用一樣,任何查詢類型都可以與pk 結合來完成一個模型上對主鍵的查詢;
F表達式
Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2) # n_pingbacks為一個字段
緩存和查詢集
使用Q對象
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
刪除對象
update
for item in my_queryset:
item.save()
聚合
- Avg:平均值;
- Count:返回對應expression的個數;
- Max:返回expression的最大值;
- Min:返回expression的最小值;
- StdDev:標准差;
- Sum:和;
- Variance:方差;
annotate() 和 values() 字句的順序
Author.objects.annotate(average_rating=Avg('book__rating')) # 根據作家id進行分組
Author.objects.values('name').annotate(average_rating=Avg('book__rating')) # 根據作家名字進行分組
默認排序交換或order_by()
Item.objects.values("data").annotate(Count("id")).order_by()
搜索
Managers
自定義管理器和模型繼承
AbstractBase.objects.do_something()
class MyManager(models.Manager):
use_for_related_fields = True # 注意是在管理器中進行定義
原生SQL語句的查詢
使用raw
for p in Person.objects.raw('SELECT * FROM myapp_person'):
print(p)
name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
使用原生orm
from django.db import connection
def my_custom_sql(self):
cursor = connection.cursor()
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
延遲加載
數據庫事務
管理事務
使用默認的管理事務
from django.db import transaction
@transaction.non_atomic_requests(using='other')
def my_other_view(request):
do_stuff_on_the_other_database()
自定義管理事務
from django.db import transaction
@transaction.atomic
def viewfunc(request):
# This code executes inside a transaction.
do_stuff()
def viewfunc(request):
# This code executes in autocommit mode (Django's default).
do_stuff()
with transaction.atomic():
# This code executes inside a transaction.
do_more_stuff()
使用原生的api
數據庫訪問優化
在模版中使用with標簽
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
在數據庫中操作而不是在Python中操作
用唯一的被索引的列來當作檢索的對象
entry = Entry.objects.get(id=10)
entry = Entry.object.get(headline="News Item Title")
一次性檢索需要的東西
獲取你想要的
使用QuerySet.values()和values_list()
使用QuerySet.defer()和only()
使用QuerySet.count()
使用QuerySet.exists()
不要過度使用count和exists
{% if display_inbox %}
{% with emails=user.emails.all %}
{% if emails %}
<p>You have {{ emails|length }} email(s)</p>
{% for email in emails %}
<p>{{ email.body }}</p>
{% endfor %}
{% else %}
<p>No messages today.</p>
{% endif %}
{% endwith %}
{% endif %}
使用QuerySet.update()和delete()
直接使用外鍵的值
entry.blog_id # 正確
entry.blog.id # 不好
沒有需要就不需要進行排序
整體插入
Entry.objects.bulk_create([
Entry(headline="Python 3.0 Released"),
Entry(headline="Python 3.1 Planned")
])
my_band.members.add(me, my_friend)