John Rogerson
John Rogerson

Reputation: 1183

Circular Dependency Error in Django

Having an issue when running makemigrations/migrate with my Django project.

Getting this error:

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

I have two apps---one called Accounts and another called Projects

for my Accounts app, here is the model:

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)

and for my Projects app here is the model. I thought that maybe since I was using a many to many field from the UserProfile to the Skill class in another app that maybe that was the issue...so i tried to run makemigrations separately on the two apps---while commenting out 'skill' from UserProfile. Didn't work. So not sure what to do now.

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())

Upvotes: 0

Views: 4226

Answers (2)

Iain Shelvington
Iain Shelvington

Reputation: 32244

Your 2 migrations have a dependency on each other. Look at the generated migration for your account app and you will probably see something like this

class Migration(migrations.Migration):

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

There is probably something similar in your projects migration

You need to delete these two migration files and run makemigrations again without specifying an app name

Upvotes: 4

Neeraj Kumar
Neeraj Kumar

Reputation: 3941

When you have this type of problem that means you are importing classes from each other. You are using each other app model classes in Foreignkey and ManytoMany fields. So use below way to define fields in your models.py of both app.

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

Upvotes: 2

Related Questions