Django Migrations Циркулярные зависимости

Итак, мой проект django работал совершенно нормально, и все работало.

Я хотел переименовать приложение в другое, поэтому я сделал это и обновил все связанные файлы, включая файл конфигурации app.py.

Я также очистил базу данных и удалил все файлы миграции из каждого приложения.

С тех пор я так и не смог завершить makemigrations на своих приложениях.

Я даже воссоздал приложение, которое переименовал, сделав django-admin startapp "appname", а затем скопировал содержимое models.py admin.py и т.д., чтобы проверить, не вызвал ли я каким-то образом внутреннюю проблему, но я просто не могу понять, что происходит

Мне удалось добиться успеха всех makemigrations для всех приложений, включая то, которое я переделал, когда удалил это (ниже) из файла admin.py другого приложения

# accounts/admin.py

class SigBotSettingsInLine(admin.StackedInline):
    model = SigBotSettings

@admin.register(Bot)
class BotAdmin(admin.ModelAdmin,):
    ...
    inlines = [SigBotSettingsInLine]

но в конце python manage.py migrate, все равно Failed. Если кто-нибудь поможет, буду очень признателен.

Вот код ошибки:

(dguacENV) PS C:\Users\Admin\Desktop\djangoProjects\dguac> python manage.py makemigrations accounts
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\core\management\commands\makemigrations.py", line 88, in handle
    loader = MigrationLoader(None, ignore_no_migrations=True)
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\db\migrations\loader.py", line 53, in __init__
    self.build_graph()
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\db\migrations\loader.py", line 286, in build_graph
    self.graph.ensure_not_cyclic()
  File "C:\Users\Admin\anaconda3\envs\dguacENV\lib\site-packages\django\db\migrations\graph.py", line 274, in ensure_not_cyclic
    raise CircularDependencyError(", ".join("%s.%s" % n for n in cycle))
django.db.migrations.exceptions.CircularDependencyError: accounts.0001_initial, accounts.0002_auto_20210809_1814, signals.0001_initial
# signals/models.py

from django.db import models
from signals import myModelFields
from datetime import datetime
from postgres_copy import CopyManager

# Create your models here.

class SignalProvider(models.Model):
    name = models.CharField(max_length=164)
    url = models.URLField(blank=True)

    def __str__(self):
        return self.name
    

class Signal(models.Model):
    date = models.DateTimeField(default=datetime.now())
    signal_ID = models.CharField(max_length=164)
    market = models.CharField(max_length=6)
    BUY = 'Buy'
    SELL = 'Sell'
    sigModeChoices = [
    (BUY, 'Buy'),
    (SELL, 'Sell'),
    ]
    signal_mode = models.CharField(max_length=4, choices=sigModeChoices, default=BUY)
    last_price = models.FloatField(max_length=10)
    exchange = models.ForeignKey('accounts.Exchange', on_delete=models.CASCADE)
    provider = models.ForeignKey('SignalProvider', on_delete=models.CASCADE)

class OpenSignal(models.Model):
    date = models.DateTimeField(default=datetime.now())
    signal_ID = models.CharField(max_length=164)
    market = models.CharField(max_length=6)
    BUY = 'Buy'
    SELL = 'Sell'
    sigModeChoices = [
    (BUY, 'Buy'),
    (SELL, 'Sell'),
    ]
    signal_mode = models.CharField(max_length=4, choices=sigModeChoices, default=BUY)
    trade_price = models.FloatField(max_length=15)
    current_price = models.FloatField(max_length=15)
    result = models.DecimalField(max_digits=4, decimal_places=2)
    # Trades to track sales
    trailing_stop_loss = models.DecimalField(max_digits=4, decimal_places=2)
    ######
    exchange = models.ForeignKey('accounts.Exchange', on_delete=models.CASCADE)
    provider = models.ForeignKey('SignalProvider', on_delete=models.CASCADE)

    objects = CopyManager()

class SigBotSettings(models.Model):
    bot_ID = models.OneToOneField(
        'accounts.Bot',
        on_delete=models.CASCADE,
        primary_key=True, related_name='sigSettings'
    )
    active = models.BooleanField(default=False)
    paid = models.BooleanField(default=False)
    enable_buys = models.BooleanField(default=True)
    API_key = models.CharField(max_length=164)
    API_secret_key = models.CharField(max_length=164)
    per_trade_percentage = myModelFields.IntegerRangeField(min_value=1, max_value=100)
    base_currency = models.CharField(max_length=8)

    objects = CopyManager()

Зависимости в accounts/migrations/0001_initial.py

dependencies = [
    ('signals', '__first__'),
    ('auth', '0012_alter_user_first_name_max_length'),
]

Зависимости в accounts/migraitons/0002_auto_20210809_1910.py

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

Зависимости в signals/migrations/0001_initial.py

dependencies = [
    ('accounts', '0002_auto_20210809_1910'),
]

Это говорит нам следующее:

  1. accounts.0001.initial depends on signals.0001_initial (specified by '__first__'.
  2. accounts.0002_auto_20210809_1910 depends on accounts.0001.initial
  3. signals.0001_initial.py depends on accounts.0002_auto_20210809_1910

Цикличность должна быть очевидна.

Вы можете либо отредактировать эти зависимости вручную, либо удалить все миграции и сгенерировать их заново с помощью ./manage.py makemigrations Это должно решить проблему, если только нет глубинных проблем с самими зависимостями модели.

ПРЕДУПРЕЖДЕНИЕ

Будьте очень осторожны при редактировании или удалении миграций. Если ваш проект развернут на живом сервере, редактирование уже примененных миграций в лучшем случае ничего не даст, а в худшем - полностью разрушит вашу производственную базу данных. Дальнейшие рекомендации следует использовать только в том случае, если вы работаете над проектом, который еще не развернут.

РЕШЕНО:

Да, большое спасибо за указание на проблему зависимости миграции, прочитав эту ссылку, я четко понял, как работает функция makemigrations.

После того, как я просмотрел свои зависимости, я обнаружил, что в моем файле Signals.models был foriegnkey, который ссылался на приложение Signals до того, как оно было перенесено.

Я закомментировал эту строку foreignkey, затем выполнил миграцию, и все прекрасно заработало.

После этого я даже добавил иностранный ключ обратно и обновил миграцию, что также сработало, поскольку на этот момент база данных сигналов уже была перенесена.

Я знаю, что это плохая практика, и собираюсь изменить способ привязки иностранного ключа с помощью другого метода.

Благодарю за помощь.

Вернуться на верх