Python的筆試題網上能搜出N個版本,Django的卻不多。
這套題我覺得出的挺好的(某公司的筆試的部分題目),難易適中,可以考察筆試者對於框架的理解和使用熟練度,展開了問,也可以問到很深的地方。
如果有什麼疏漏,歡迎留言探討。
Django的Model的繼承有幾種形式,分別是什麼?
一、抽象繼承:
順便複習OOP思想,繼承是物件導向的大前提╮(╯▽╰)╭,抽象類,之所以被建立是用來被繼承的;一個類如果包含任何一種抽象方法,那麼它就是抽象類;抽象方法一定要在子類中被複寫;在繼承關係中,抽象類永遠在樹枝節點上……扯遠了,而且對於Python來說,已經沒有這麼多約束了。
回到Django的Model,也一樣,當我們需要某些公共方法欄位時,就需要一個父類為其他子類服務,這個父類沒有manager,Django也不為這個類建立表,這種繼承的定義方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
class Animal(models.Model): name = models.CharField(max_length=50) age = models.PositiveIntegerField() # 下面這句決定了Animal是一個抽象類/Model class Meta: abstract = True class Human(Animal): kind_hearted = models.BooleanField() sex = models.CharField('sex', choices=(('m','male'), ('f', 'female')), max_length=1) #... |
上例中,我們的Human子model中,自然包含了name和age的欄位,但是Animal不能作為正常model使用,由於沒有manager,所以也不能例項化、儲存。在子類中,不可以建立與這個抽象父類中的相同的欄位,Django表示對報錯負責。
二、正常的繼承,多重繼承,Joined對映
和抽象繼承的主要區別是父類這時也可以擁有資料庫表了,並且不在身為儲存公共資訊的抽象類了,父類也可以進行例項化,查詢等操作了。
1 2 3 4 5 6 7 |
class Country(models.Model): name = models.CharField(max_length=10) #... class Province(Country): return = models.BooleanField() #... |
三、代理
即在子類中只能增加方法,而不能增加屬性,在不影響父類資料儲存的前提下,使子類繼承父類,此時子類稱為父類的“代理”。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from django.contrib.auth.models import User class Person(User): # this makes a class proxy proxy = True def can_dance(self): return True # both Yellow and Black can_dance :) class Yellow(Person): hometown = models.CharField(max_length=30) class Black(Person) tribe_name = models.CharField(max_length=100) |
我們為Person類增加了一個方法,可以跳舞,並且保持了User的資料欄位的不變。
Django的Queryset是什麼,objects是什麼,objects在哪裡可以定義。
query + set,已經能猜出大概,它對應著資料庫中的若干條記錄。
例如有一個叫做Order的模型,在project的根目錄下進入shell進行操作:
1 2 3 4 5 6 7 8 |
$python manage.py shell >>>from app.order.models import Order >>>type(Order.objects) <class 'django.db.models.models.manager.Manager'> >>> >>>order = Order.objects.all() >>>type(order) <class 'django.db.models.query.QuerySet'> |
上述方法很常用,看繼承關係去理解Queryset和objets。objects是每個Model預設的manager類,通過manager的方法(也可通過QuerySet的方法得到,當然QuerySet也來自於manager),得到相應的Queryset,用以對資料庫模型欄位進行更多的操作。
objects(manager)方法可以自定義新增,也可以直接賦值覆蓋掉預設的管理方法。
試著新增一個新的管理器的步驟是這樣,首先定義一個manager類繼承自models.Manager
,並在其中對self進行操作,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# new manager class OrderManager(models.Manager): def title_count(self, keyword): return self.filter(title__icontains=keyword).count() class Order(models.Models): title = models.CharField(max_length=100) # ... #objects = models.Manager() objects = OrderManager() def __unicode__(self): return self.title |
上述例子中我們把OrderManager
賦值給了objects,替換了預設的管理器。
tips:如果增加了新的管理器,且沒有替換掉預設管理器,那麼預設管理器需要顯式的宣告出來才可以使用。
Django中查詢queryset時什麼情況下用Q?
在進行相對複雜的查詢時,使用django.db.models.Q
物件。
例如需要進行復合條件的查詢的SQL語句如下:
1 |
SELECT * FROM order WHERE id BETWEEN 20 ADN 100 AND(num <= '20' or num >= '30'); |
使用Q就可以寫成:
1 2 3 4 5 6 7 |
from django.db.models import Q from login.models import Order #... Order.objects.get( Q(id >= 20) & (id <= 100), Q(num <= 20) | (num >= 30) ) |
Django中想驗證表單提交是否格式正確需要用到Form中的哪個函式?
is_valid()
函式方法,用於檢查表單提交是否正確。
Django取消級聯刪除
這個文件寫的比較清楚:
1 |
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL) |
並且SET_NULL
只有在null
為True的時候,才可以使用。
Django中如何在Model儲存前做一定的固定操作,比如寫一句日誌?
關鍵詞: 訊號
利用Django的Model的Signal Dispatcher, 通過django.db.models.signals.pre_save()
方法,在事件發生前,發射觸發訊號,這一切都被排程中的receiver方法深藏功與名的儲存了。
訊號的處理一般都寫在Model中,舉個例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import logging from django.db import models from django.db.models.signals import pre_save from django.dispatch import receiver class Order(models.Model): # ... logger = logging.getLogger(__name__) @receiver(pre_save, sender=Order) def pre_save_handler(sender, **kwargs): # 我們可以在Order這個Model儲存之前盡情調戲了:) logger.debug("{},{}".format(sender, **kwargs)) print 'fuck universe' |
這樣應該就實現了題中的要求,類似的方法還有比如pre_init
是在Model例項之前會觸發,post_init
在例項之後觸發,同理就是pre_save
和post_save
了。
Django中如何讀取和儲存session,整個session的執行機制是什麼。
說到session的執行機制,就一定要先說一下cookie這一段資訊。一般情況下cookies都是我們的瀏覽器生成的(顯然可以人為修改),用於伺服器對戶進行篩選和維護,但是這個聽上去很好吃的東西,能存的東西有點少而且容易被別人利用。這時候基於cookies的session的意義就比較明顯了,在客戶端的cookies中我們只儲存session id,而將完整資訊以加密資訊的形式儲存到伺服器端,這樣伺服器可以根據session id相對安全的在資料庫中查詢使用者的更細緻的資訊和狀態。
在Django中session和cookies的操作方法一樣,如下:
1 2 3 4 5 6 |
# 儲存session request.session['order_id'] = order_id # 刪除session del request.session['order_id'] # 讀取session session.get('order_id', False) |