Closed EsGeh closed 3 years ago
Hi! I will try to take a look into it this week. Thanks for reporting this issue
Hi, I'm not able to reproduce this bug. I think you have a model with a foreign key to a scheduler model, can you confirm this?
If you have a model with a foreign key to one scheduler model, you will need to change the type of the foreign key. Please check migration 0013
I think you have a model with a foreign key to a scheduler model, can you confirm this?
Yes, definitely. This is in my models.py
:
import schedule.models as schedule
...
class EventInfo(schedule.Event):
...(other fields)...
event_ptr = models.OneToOneField(
schedule.Event,
on_delete=models.CASCADE,
parent_link = True,
primary_key=True,
related_name="event_info"
)
(Side note: By the way, if there is a better method to extend django-scheduler
s base classes, I'd be happy for a hint.)
If you have a model with a foreign key to one scheduler model, you will need to change the type of the foreign key.
What does that mean? What other types of foreign keys are there?
Hi, In migration 0013 all models id were upgraded to BigAutoField. When you use FK in MySQL, both columns must be the same type. In your case, your models are using different column type for the event_id (to the one which is an fk to scheduler model). Our migration changed the type and this broke your extension.
I think you are extending scheduler the proper way, this was an unexpected issue.
Hope it helps.
Fixing this issue and migrating the database according to the changes introduced by django-scheduler > 0.9.3 was a nightmare. Finally I was able to fix this issue for my project. I am going to share my approach here in the hope of helping others to save time:
Given you have a model that depends on a Model in django-scheduler (python import: schedule
):
import schedule.models as schedule
...
class EventInfo(schedule.Event):
...(other fields)...
event_ptr = models.OneToOneField(
schedule.Event,
on_delete=models.CASCADE,
parent_link = True,
primary_key=True,
related_name="event_info"
)
We shall introduce 2 migrations:
your_app/migrations/0020_cut_foreign_keys.py
:
from django.db import migrations, models
import django.db.models.deletion
def copy_to_backup(apps, schema_editor):
EventInfo = apps.get_model('your_app', 'EventInfo')
EventInfoBackup = apps.get_model('event_calendar', 'EventInfoBackup')
for x in EventInfo.objects.all():
copy = EventInfoBackup(
event_ptr = x.pk,
# ...other fields...
)
# for every ManyToManyField field "m2mField":
# copy.m2mField.set(
# x.m2mField.all()
# )
copy.save()
for x in EventInfo.objects.all():
x.delete(
keep_parents = True
)
def copy_to_backup_reverse(apps, schema_editor):
EventInfo = apps.get_model('your_app', 'EventInfo')
EventInfoBackup = apps.get_model('your_app', 'EventInfoBackup')
EventBase = apps.get_model( 'schedule', 'Event' )
for copy in EventInfoBackup.objects.all():
event = EventBase.objects.get(
pk = copy.event_ptr
)
x = EventInfo(
event_ptr = event,
start = event.start,
end = event.end,
title = event.title,
description = event.description,
creator = event.creator,
created_on = event.created_on,
updated_on = event.updated_on,
rule = event.rule,
end_recurring_period = event.end_recurring_period,
calendar = event.calendar,
color_event = event.color_event,
)
x.event_ptr = event
# for every field in EventInfo:
# x.field = copy.field
x.save()
# for every ManyToManyField in EventInfo:
x.m2mField.set(
copy.m2mField.all()
)
x.save()
class Migration(migrations.Migration):
dependencies = [
('you_app', '0019_...'), # <-- previous migration
('schedule', '0012_auto_20191025_1852'),
]
run_before = [
('schedule', '0013_auto_20210502_2303'),
]
operations = [
migrations.CreateModel(
name='EventInfoBackup',
fields=[
('event_ptr', models.IntegerField(primary_key=True)),
# ...other fields...
],
),
# Copy EventInfos to backup
migrations.RunPython(
code = copy_to_backup,
reverse_code = copy_to_backup_reverse
),
migrations.DeleteModel(
name = 'EventInfo',
)
]
your_app/migrations/0021_repair_foreign_keys.py
:
from django.db import migrations, models
import django.db.models.deletion
def copy_from_backup(apps, schema_editor):
EventInfo = apps.get_model('your_app', 'EventInfo')
EventInfoBackup = apps.get_model('your_app', 'EventInfoBackup')
EventBase = apps.get_model( 'schedule', 'Event' )
for copy in EventInfoBackup.objects.all():
event = EventBase.objects.get(
pk = copy.event_ptr
)
x = EventInfo(
event_ptr = event,
start = event.start,
end = event.end,
title = event.title,
description = event.description,
creator = event.creator,
created_on = event.created_on,
updated_on = event.updated_on,
rule = event.rule,
end_recurring_period = event.end_recurring_period,
calendar = event.calendar,
color_event = event.color_event,
)
# for every field "field" in EventInfo:
x.field = copy.field
x.event_ptr = event
x.save()
# for every ManyToManyField "m2mField":
# x.m2mField.set(
# copy.m2mField.all()
# )
x.save()
def copy_from_backup_reverse(apps, schema_editor):
EventInfo = apps.get_model('your_app', 'EventInfo')
EventInfoBackup = apps.get_model('your_app', 'EventInfoBackup')
for x in EventInfo.objects.all():
copy = EventInfoBackup(
event_ptr = x.pk
# ...for all fields "field" except ManyToManyFields...
# field = x.field,
)
# for every ManyToManyField "m2mField":
# copy.m2mField.set(
# x.m2mField.all()
# )
copy.save()
for x in EventInfo.objects.all():
x.delete(
keep_parents = True
)
class Migration(migrations.Migration):
dependencies = [
('your_app', '0020_cut_foreign_key'),
('schedule', '0014_use_autofields_for_pk'),
]
operations = [
migrations.CreateModel(
name='EventInfo',
fields=[
('event_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='event_info', serialize=False, to='schedule.event')),
# ...other fields in EventInfo...
],
bases=('schedule.event',),
),
# Copy EventInfos from backup
migrations.RunPython(
code = copy_from_backup,
reverse_code = copy_from_backup_reverse
),
migrations.DeleteModel(
name='EventInfoBackup',
),
]
Thanks for providing that information! I'm closing this issue. I will take a look to the open PR.
Hello devs,
after upgrading from version 0.9.3 to any later version, i get an error when trying to migrate. This is obviously related to the migration 0013 and MySQ...
Output when running migrations:
System information: