2011-06-16 84 views
4

可能有人請解釋這種現象:奇怪Django的進口行爲

Django項目稱爲foo

文件bar/models.py

class MyModelError(TypeError): 
    pass 

class MyModel(models.Model): 
    ... 

./manage.py shell

>>> from foo.bar.models import MyModel as m1 
>>> from bar.models import MyModel as m2 
>>> from foo.bar.models import MyModelError as e1 
>>> from bar.models import MyModelError as e2 
>>> m1 is m2 
True 
>>> e1 is e2 
False 

假?

>>> m1 
<class 'foo.bar.models.MyModel'> 
>>> m2 
<class 'foo.bar.models.MyModel'> 
>>> e1 
<class 'foo.bar.models.MyModelError'> 
>>> e1 
<class 'bar.models.MyModelError'> 

任何想法,我在做什麼錯在這裏?我的解決方法(除了確保我導入'正確的方式')是使錯誤類成爲模型本身的成員(如django model.DoesNotExists)但我想知道發生了什麼

+0

不要使用點作爲模塊名稱的一部分。 – 2011-06-16 11:56:07

+1

我相當確定這是一個錯字,因爲您無法通過'import'在名稱中導入帶有點的模塊。 – 2011-06-16 11:58:09

+0

確實是一個錯字。固定 – second 2011-06-16 11:59:51

回答

4

Django使用元類用於定義模型。在那裏有一個檢查來避免定義一個模型兩次,所以當一個類被創建時,如果它已經被定義,那麼你會得到之前定義的版本。見django.db.models.base.ModelBase

from django.db.models.loading import get_model 

# Bail out early if we have already created this class. 
m = get_model(new_class._meta.app_label, name, False) 
if m is not None: 
    return m 

而錯誤類是常規的Python類和有你不同的版本沒有此緩存,因爲模塊它們屬於不同。我認爲,出現這種情況,是因爲運行的Django時的runserver您從路徑加載同一模塊的兩種方式結束:

  • 當前目錄
  • 當前目錄上面的目錄

這是以便您可以導入完全限定的軟件包(包括項目名稱)並使其工作。

我傾向於不使用項目名稱導入來避免此問題。

0

在大多數編程語言中,錯誤掛起具有階梯式機制。所以如果發生錯誤,異常機制開始搜索處理錯誤的異常。如果在該類中無法處理異常,它會通過該類從其派生而來的類繼續搜索上層... ....它使此過程始終處於繼承的最高級別...

因此,您正在定義ModelError派生的類TypeError,並從不同的路徑導入該類可能可能導致python interpereter將這兩個類別識別爲不同的類。

Python Documentation