繁体   English   中英

Django中的循环依赖错误

[英]Circular Dependency Error in Django

在我的Django项目中运行makemigrations / migration时遇到问题。

收到此错误:

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\__init__.py", line 353, in execute_from_command_line
    utility.execute()
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\__init__.py", line 345, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\base.py", line 348, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\base.py", line 399, in execute
    output = self.handle(*args, **options)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\commands\migrate.py", line 139, in handle
    plan = executor.migration_plan(targets)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\executor.py", line 60, in migration_plan
    for migration in self.loader.graph.forwards_plan(target):
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\graph.py", line 149, in forwards_plan
    self.ensure_not_cyclic(target, lambda x: (parent.key for parent in self.node_map[x].parents))
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\graph.py", line 241, in ensure_not_cyclic
    raise CircularDependencyError(", ".join("%s.%s" % n for n in cycle))
django.db.migrations.exceptions.CircularDependencyError: accounts.0001_initial, projects.0001_initial

我有两个应用程序-一个叫做“帐户”,另一个叫做“项目”

对于我的“帐户”应用,模型如下:

from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin
)
from django.db import models
from django.utils import timezone
from django.conf import settings
from django.db.models.signals import post_save
import os

from projects.models import Skill, Project


def avatar_upload_path(instance, filename):
    return os.path.join('avatars', 'user_{0}', '{1}').format(
        instance.user.id, filename)

class UserManager(BaseUserManager):
    def create_user(self, email, username=None, password=None):
        if not email:
            raise ValueError("Users must have an email address")

        if not username:
            username = email.split('@')[0]

        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email,
            username,
            password,
        )
        user.is_staff = True
        user.is_superuser = True
        user.save()
        return user


class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=40, unique=True, default='')
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def __str__(self):
        return "@{}".format(self.username)

    def get_short_name(self):
        return self.username

    def get_long_name(self):
        return "@{} ({})".format(self.username, self.email)


class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)
    first_name = models.CharField(max_length=40, default='', blank=True)
    last_name = models.CharField(max_length=40, default='', blank=True)
    bio = models.TextField(blank=True, default='')
    avatar = models.ImageField('Avatar picture',
                               upload_to=avatar_upload_path,
                               null=True,
                               blank=True)
    skills = models.ManyToManyField(Skill)

    def __str__(self):
        return self.user.username

    @property
    def get_avatar_url(self):
        if self.avatar:
            return '/media/{}'.format(self.avatar)
        return 'http://www.gravatar.com/avatar/{}?s=128&d=identicon'.format(
            '94d093eda664addd6e450d7e9881bcad'
        )


def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

对于我的Projects应用程序,这里是模型。 我以为可能是因为我在另一个应用程序中使用了从UserProfile到Skill类的多对多字段,也许就是问题所在...所以我尝试在两个应用程序上分别运行makemigrations-注释掉“技能”。 没用 所以不确定现在该怎么办。

from django.conf import settings
from django.db import models

from django.core.urlresolvers import reverse

class Skill(models.Model):
    """User skills class."""
    ANDROID = 1
    DESIGNER = 2
    JAVA = 3
    PHP = 4
    PYTHON = 5
    RAILS = 6
    WORDPRESS = 7
    IOS = 8

    SKILL_CHOICES = (
        (str(ANDROID), 'Android Developer'),
        (str(DESIGNER), 'Designer'),
        (str(JAVA), 'Java Developer'),
        (str(PHP), 'PHP Developer'),
        (str(PYTHON), 'Python Developer'),
        (str(RAILS), 'Rails Developer'),
        (str(WORDPRESS), 'Wordpress Developer'),
        (str(IOS), 'iOS Developer')
    )

    name = models.CharField(max_length=140, choices=SKILL_CHOICES, default='unknown')

    def __str__(self):
        return self.get_name_display()


class Project(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='project', null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=255)
    description = models.TextField()
    requirements = models.TextField(default='')
    timeline = models.CharField(max_length=255, blank=True)
    complete = models.BooleanField(default=False)

    @property
    def open_positions(self):
        return self.positions.exclude(filled=True)

    def __str__(self):
        return self.title.title()

    def get_absolute_url(self):
        return reverse("projects:project_detail", kwargs={"pk": self.pk})


class Position(models.Model):
    project = models.ForeignKey(Project, default='',related_name='positions')
    name = models.CharField(max_length=140)
    description = models.TextField()
    skill = models.ForeignKey(Skill, default='', null=True)
    filled = models.BooleanField(default=False)

    def __str__(self):
        return '{} - {}'.format(self.project.title.title(), self.name.title())

您的2个迁移相互依赖。 查看为您的帐户应用程序生成的迁移,您可能会看到类似以下的内容

class Migration(migrations.Migration):

    dependencies = [
        ('projects', '0001_initial'),
    ]

您的项目迁移中可能存在相似之处

您需要删除这两个迁移文件并再次运行makemigrations ,而无需指定应用程序名称

当您遇到此类问题时,意味着您正在互相导入类。 您正在Foreignkey和ManytoMany字段中互相使用其他应用程序模型类。 因此,请使用以下方式在两个应用程序的models.py中定义字段。

 field = models.ForeignKey('app_name.ModelClassName',)
 field = models.ManyToManyField('app_name.ModelClassName',)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM