アプリケーションを Django 1.11.25 (Python 2.6) から Django 3.1.3 (Python 3.8.5) にアップグレードしていますが、 を実行するとmanage.py makemigrations
、次のメッセージが表示されます。
File "/home/eduardo/projdevs/upgrade-intra/corporate/models/section.py", line 9, in <module>
from authentication.models import get_sentinel**
ImportError: cannot import name 'get_sentinel' from partially initialized module 'authentication.models' (most likely due to a circular import) (/home/eduardo/projdevs/upgrade-intra/authentication/models.py)**
私のモデルは次のとおりです:
認証 / models.py
from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
from django.db.models.signals import post_save
from django.utils import timezone
from corporate.constants import GROUP_SUPPORT
from corporate.models import Phone, Room, Section
from library.exceptions import ErrorMessage
from library.model import update_through_dict
from .constants import INTERNAL_USER, EXTERNAL_USER, SENTINEL_USERNAME, SPECIAL_USER, USER_TYPES_DICT
class UserProfile(models.Model):
user = models.OneToOneField(
'User',
on_delete=models.CASCADE,
unique=True,
db_index=True
)
...
phone = models.ForeignKey('corporate.Phone', on_delete=models.SET_NULL, ...)
room = models.ForeignKey('corporate.Room', on_delete=models.SET_NULL, ...)
section = models.ForeignKey('corporate.Section', on_delete=models.SET_NULL, ...)
objects = models.Manager()
...
class CustomUserManager(UserManager):
def __init__(self, type=None):
super(CustomUserManager, self).__init__()
self.type = type
def get_queryset(self):
qs = super(CustomUserManager, self).get_queryset()
if self.type:
qs = qs.filter(type=self.type).order_by('first_name', 'last_name')
return qs
def get_this_types(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(type__in=types).order_by('first_name', 'last_name')
return qs
def get_all_excluding(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(~models.Q(type__in=types)).order_by('first_name', 'last_name')
return qs
class User(AbstractUser):
type = models.PositiveIntegerField('...', default=SPECIAL_USER)
username = models.CharField('...', max_length=256, unique=True)
first_name = models.CharField('...', max_length=40, blank=True)
last_name = models.CharField('...', max_length=80, blank=True)
date_joined = models.DateTimeField('...', default=timezone.now)
previous_login = models.DateTimeField('...', default=timezone.now)
objects = CustomUserManager()
...
def get_profile(self):
if self.type == INTERNAL_USER:
...
return None
def get_or_create_profile(self):
profile = self.get_profile()
if not profile and self.type == INTERNAL_USER:
...
return profile
def update(self, changes):
...
class ExternalUserProxy(User):
objects = CustomUserManager(type=EXTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
class InternalUserProxy(User):
objects = CustomUserManager(type=INTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
def create_profile(sender, instance, created, **kwargs):
if created and instance.type == INTERNAL_USER:
try:
profile = UserProfile()
profile.user = instance
profile.save()
except:
pass
post_save.connect(create_profile, sender=User)
def get_sentinel():
try:
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
except User.DoesNotExist:
settings.LOGGER.error("...")
from django.contrib.auth.models import Group
sentinel = User()
sentinel.username = SENTINEL_USERNAME
sentinel.first_name = "..."
sentinel.last_name = "..."
sentinel.set_unusable_password()
sentinel.save()
technical = Group.objects.get(name=GROUP_SUPPORT)
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
sentinel.groups.add(technical)
sentinel.save()
return sentinel
企業 / モデル /__init__.py
...
from .section import Section
...
企業 / モデル / section.py
from django.conf import settings
from authentication.models import get_sentinel
from .room import Room
class Section(models.Model):
...
boss = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
surrogate = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
room = models.ForeignKey(Room, on_delete=models.SET_NULL, ...)
is_subordinate_to = models.ForeignKey('self', on_delete=models.SET_NULL, ...)
...
何が間違っているのでしょうか?
ベストアンサー1
将来の読者のために言っておくと、これは、プロジェクトが使用する依存関係と同じ名前を Python ファイルに付けた場合にも発生する可能性があります。
例えば:
再試行パッケージを使用している retrying.py という名前のファイルを持つことはできません。
プロジェクトに再試行パッケージがあると仮定すると、以下の内容の retrying.py というファイルを作成することはできません。
from retrying import retry
print("HI")
「循環インポートが原因の可能性が高い」というメッセージとともに同様のエラーが発生します。
ファイル名を「retrying_example1.py」に変更すると、同じ内容が問題なく動作します。