[英]Django Attribute Error: module 'appname' has not attribute models
我知道我的問題可能涉及共同/循環進口,因此我在發布之前進行了搜索。 我發現當前可以解決我問題的唯一解決方案是將導入移動到文件之一的末尾,就在實際使用導入函數之前。 但是我也讀過,不建議這樣做。
推薦的解決方案,只需執行以下操作:
在A.py
> import B
並在B.py
-> import A
然后訪問功能,將無法正常工作。
因此,我在Django應用程序中有三個應用程序:“核心”,“通知”和“帳戶”。 以下是他們的摘錄:
core.models:
from django.db import models
from django.contrib.auth.models import User
import notifications.models
from z_misc import general_scripts
# Create your models here.
class BaseModel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
這是我在core.models
使用Notification
的core.models
:
# inspect mb for each artist
### Assume class is defined and @classmethod is intended, having some formatting pains here
@classmethod
def refresh_from_mb(cls):
artists = cls.get_artists_with_subs()
for artist in artists:
added_rgs = general_scripts.refresh_artist(artist.mbid)
for rg in added_rgs:
new_notification = Notification(artist_id=artist.id, release_group=rg)
new_notification.save()
notification.models:
from django.db import models
import core.models
import accounts.models
class Notification(core.models.BaseModel):
artist_id = models.OneToOneField(core.models.Artist, related_name="artist_notifications", null=False)
release_group = models.OneToOneField(core.models.ReleaseGroup, related_name="rg_notifications", null=False)
def get_rg_type(self):
return self.release_group.type
account.models:
from django.db import models
from django.contrib.auth.models import User
import core.models
from django.db.models import Q
# Create your models here.
class UserProfile(core.models.BaseModel):
#TODO: add email_activated = models.BooleanField(default=False)
user = models.OneToOneField(User, related_name="user_profile")
如您所見,我遵循的建議不是from
,然后是import
,而是先import
,然后使用完整的表示法。 沒用 完整的錯誤回溯是:
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x10fa9af28>
Traceback (most recent call last):
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
autoreload.raise_last_exception()
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 251, in raise_last_exception
six.reraise(*_exception)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models()
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/Users/username/.pyenv/versions/3.6.1/lib/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 978, in _gcd_import
File "<frozen importlib._bootstrap>", line 961, in _find_and_load
File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
File "/Users/username/PycharmProjects/artist_notify/core/models.py", line 3, in <module>
import notifications.models
File "/Users/username/PycharmProjects/artist_notify/notifications/models.py", line 3, in <module>
import accounts.models
File "/Users/username/PycharmProjects/artist_notify/accounts/models.py", line 8, in <module>
class UserProfile(core.models.BaseModel):
AttributeError: module 'core' has no attribute 'models'
我不確定目前該如何解決。 除了開始將導入語句移動到文件的中間/結尾外,這似乎是一個很大的禁忌。
請不要建議我from app.models import ModelName
,因為這是我之前使用的,直到由於循環導入而開始出現錯誤。
在設計過程中需要避免循環引用,尤其是導入。 IOW,這是設計錯誤,而不是實現錯誤。 簡化的情況是( A -> B
表示A
是由B
導入/導入B
, N
=通知, C
=核心, A
=帳戶):
N -> C
C -> N
A -> C
A -> N
如果我們以圖形方式繪制它,很容易看到我們只需要解決C
和N
之間的圓度問題:
即我們只需要刪除C
和N
之間的箭頭/導入之一。
Django具有許多可用於解耦圓形參考圖的功能,例如:
使用字符串引用:到外鍵中的模型,所以代替
from core.models import ReleaseGroup # this is how you should import models
class Notification(...):
release_group = models.OneToOneField(ReleaseGroup, ..)
你會做:
# no import of ReleaseGroup model
class Notification(...):
release_group = models.OneToOneField('core.models.ReleaseGroup', ..)
Django具有一些有用的功能,例如,您可以多次遍歷關系並避免導入,例如:
Notification.objects.filter(release_group=ReleaseGroup.objects.get(pk=1))
這需要同時導入Notification
和ReleaseGroup
,您可以執行以下操作:
Notification.objects.filter(release_group__pk=1)
通常,您需要使用組合,提取,移動中的一項或多項。
合並:這很簡單,如果將C
和N
合並到一個更大的模塊中,那么您已經解決了圓度問題(一個文件中的圓度非常好)。
提取:如果您可以找到一些可以插入到新模塊中的代碼子集,使得該新模塊位於導入圖的頂部或底部,那么您已經解決了圓度問題,例如,如果您有兩個模塊,具有許多模型,但其中只有兩個具有循環引用(此處為X2和Y2):
x.py:
class X1(Model):
...
class X2(Model):
y2 = ForeignKey(Y2)
class X3...
y.py:
class Y1(...): ..
class Y2(Model):
x2 = ForeignKey(X1)
...
然后可以通過引入新模塊來解決圓度問題(x.py和y.py將從xy.py分別導入X2和Y2)
xy.py:
class X2(Model):
y2 = ForeignKey(Y2)
class Y2(Model):
x2 = ForeignKey(X1)
將其他模型留在原處。 (注意:提取也只能與一種模型一起使用-我認為您的BaseModel
可能是提取的候選對象)。
move:從本質上講類似於提取,您會發現一小段引起圓度的代碼並將其移至另一個現有模塊,從而不再導致圓度。 在上面的示例中,X2可能已移至y.py或Y2可能已移至x.py。
我不知道您在哪里閱讀該建議,但這是完全錯誤的。 循環導入是循環導入,無論您使用哪種形式的import語句。
這里的解決方案是根本不將模型導入核心。 您似乎不需要它們,因為您沒有提到它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.