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'), ]
Это говорит нам следующее:
accounts.0001.initial
depends onsignals.0001_initial
(specified by'__first__'
.accounts.0002_auto_20210809_1910
depends onaccounts.0001.initial
signals.0001_initial.py
depends onaccounts.0002_auto_20210809_1910
Цикличность должна быть очевидна.
Вы можете либо отредактировать эти зависимости вручную, либо удалить все миграции и сгенерировать их заново с помощью ./manage.py makemigrations
Это должно решить проблему, если только нет глубинных проблем с самими зависимостями модели.
ПРЕДУПРЕЖДЕНИЕ
Будьте очень осторожны при редактировании или удалении миграций. Если ваш проект развернут на живом сервере, редактирование уже примененных миграций в лучшем случае ничего не даст, а в худшем - полностью разрушит вашу производственную базу данных. Дальнейшие рекомендации следует использовать только в том случае, если вы работаете над проектом, который еще не развернут.
РЕШЕНО:
Да, большое спасибо за указание на проблему зависимости миграции, прочитав эту ссылку, я четко понял, как работает функция makemigrations.
После того, как я просмотрел свои зависимости, я обнаружил, что в моем файле Signals.models был foriegnkey, который ссылался на приложение Signals до того, как оно было перенесено.
Я закомментировал эту строку foreignkey, затем выполнил миграцию, и все прекрасно заработало.
После этого я даже добавил иностранный ключ обратно и обновил миграцию, что также сработало, поскольку на этот момент база данных сигналов уже была перенесена.
Я знаю, что это плохая практика, и собираюсь изменить способ привязки иностранного ключа с помощью другого метода.
Благодарю за помощь.