我正在将应用程序从 Django 1.11.25(Python 2.6)升级到 Django 3.1.3(Python 3.8.5),当我运行时manage.py makemigrations,我收到此消息:
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)**
我的模型是:
身份验证/模型.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
__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, ...) ...
我做错什么了?
您有一个循环导入。
authentication/models进口corporate/models,哪些进口corporate/models/section,哪些进口authentication/models。
authentication/models
corporate/models
corporate/models/section
你不能这么做。重写和/或重新排列你的模块,这样就不需要循环导入了。
实现此目的的一种策略是将模块组织成层次结构,并确保模块仅导入层次结构中较低的其他模块。(此层次结构可以是实际的目录结构,但不一定是;它可以只是程序员头脑中的一个心理记号。)