Cannot correct a failed migration django - django

I inadvertently did this:
ordering = models.IntegerField(default="Order/position")
I ran makemigrations and got no error. When I ran migrate it blew up with the error:
ValueError: invalid literal for int() with base 10: 'Order/position'
what I had meant to do was this:
ordering = models.IntegerField(default=0, verbose_name="Order/Position")
I updated to the correct field definition and while makemigrations is happy and noted the change migrate still keeps throwing that same error.
How do I fix this?
In case this matters - I am running Django with Postgres and both are in Docker containers
Is it possible to "cancel" a previously failed migration?
Is it common for makemigration to not catch big errors like this?

The best is probably to fix the migration file itself. In the migration file, it will probably looked like:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
# …
]
operations = [
migrations.CreateModel(
name='MyModel',
fields=[
(
'id',
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID',
),
),
(
'ordering',
models.IntegerField(
default='Order/position',
),
),
],
)
]
You fix this by altering the definition for ordering to the IntegerField you described.

Related

Django incomplete migration of table with multiple foreign keys

Django version: 4.1.2
After heaving the following table defined in the model:
class Tasks(models.Model):
name_text = models.CharField(max_length=200)
duration_int = models.IntegerField(default=1)
...
the next two tables have been defined:
class Metiers(models.Model):
name_text = models.CharField(max_length=50)
...
class TasksProperties(models.Model):
task = models.ForeignKey(Tasks, on_delete=models.CASCADE, related_name='task_relation')
metier = models.ForeignKey(Metiers, on_delete=models.CASCADE, related_name='metier_relation')
...
doing the migration, the metier is not created inside the SQL table, but the rest:
class Migration(migrations.Migration):
dependencies = [
('simo', '0009_alter_specialdays_day_date'),
]
operations = [
migrations.CreateModel(
name='Metiers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name_text', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='TasksProperties',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('workload_mh', models.IntegerField(default=8)),
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='simo.tasks')),
],
),
]
Is there any reason, why metier is not taken into account?
Update on 27/11/2022:
So, it still not clear why it was not working because I believe the structure is correct; therefore I did some try-on-errors and finally the migration is complete, although the reason is not obvious. See below the resolution:
Step 1) Remove the migrated TaskProperties class from models and do a migration
Step 2) models.py was updated as
class TasksProperties(models.Model):
workload_mh = models.IntegerField(default=8)
metier = models.ForeignKey('Metiers', on_delete=models.CASCADE, related_name='metier_relation')
It resulted that the "metier" as foreignkey was visible in SQL after the migration.
Step 3) Adding the "task" as well, the migration dropped the following question:
class TasksProperties(models.Model):
workload_mh = models.IntegerField(default=8)
metier = models.ForeignKey('Metiers', on_delete=models.CASCADE, related_name='metier_relation')
task = models.ForeignKey(Tasks, on_delete=models.CASCADE, related_name='task_relation')
*It is impossible to add a non-nullable field 'task' to tasksproperties without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
Provide a one-off default now (will be set on all existing rows with a null value for this column)
Quit and manually define a default value in models.py.
Select an option: 2*
Then after updating the model.py adding default value default=0 to "task" the migration was successful:
class TasksProperties(models.Model):
workload_mh = models.IntegerField(default=8)
metier = models.ForeignKey('Metiers', on_delete=models.CASCADE, related_name='metier_relation')
task = models.ForeignKey(Tasks, on_delete=models.CASCADE, related_name='task_relation', default=0)
Why is this "defualt" value is needed?
Try these three commands:
python manage.py makemigrations appname
python manage.py sqlmigrate appname 0001
python manage.py migrate
And see if it solves

django keeps creating new migrations even when model has not changed

The following is my model:
class Biovariable(models.Model):
bioid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=200)
description = models.CharField(max_length=2000)
units = models.ForeignKey(unit, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Biovariable_data(models.Model):
biovar = models.ForeignKey(Biovariable, on_delete=models.CASCADE)
value = models.CharField(max_length=2000)
evdate = models.CharField(max_length=30)
evtime = models.CharField(max_length=30)
linkedcustomer = models.ForeignKey(customer, on_delete=models.CASCADE)
linkeddoctor = models.ForeignKey(doctor, on_delete=models.CASCADE)
linkedclinic = models.ForeignKey(Clinic, on_delete=models.CASCADE)
class Meta:
unique_together = [
"biovar", "value", "evdate", "evtime", "linkedcustomer",
"linkeddoctor", "linkedclinic"
]
Each time I run makemigrations, django keeps creating new migrations, and I cant understand why.
joel#hp:~/myappointments$ ./manage.py makemigrations
Migrations for 'appointments':
appointments/migrations/0010_auto_20190310_2138.py
- Add field dob to customer
- Alter field biovar on biovariable_data
joel#hp:~/myappointments$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, appointments, auth, clinic, contenttypes, sessions
Running migrations:
Applying appointments.0010_auto_20190310_2138... OK
joel#hp:~/myappointments$ ./manage.py makemigrations
Migrations for 'appointments':
appointments/migrations/0011_auto_20190310_2139.py
- Alter field biovar on biovariable_data
joel#hp:~/myappointments$ ./manage.py makemigrations
Migrations for 'appointments':
appointments/migrations/0012_auto_20190310_2139.py
- Alter field biovar on biovariable_data
joel#hp:~/myappointments$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, appointments, auth, clinic, contenttypes, sessions
Running migrations:
Applying appointments.0011_auto_20190310_2139... OK
Applying appointments.0012_auto_20190310_2139... OK
joel#hp:~/myappointments$ ./manage.py makemigrations
Migrations for 'appointments':
appointments/migrations/0013_auto_20190310_2140.py
- Alter field biovar on biovariable_data
joel#hp:~/myappointments$
One of these migration files looks like this:
# Generated by Django 2.1.3 on 2019-03-10 16:09
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('appointments', '0010_auto_20190310_2138'),
]
operations = [
migrations.AlterField(
model_name='biovariable_data',
name='biovar',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='appointments.Biovariable'),
),
]
I had the same problem but nothing in my model was dynamic. This occurred for me after changing the name of the model in question. (For reference it was a many to many through model which I renamed from "Enrollment" to "Registration").
Answering to provide a more explicit solution which was:
# 1 - Roll back migrations
python manage.py migrate <app_name> zero>
# 2 - Delete the migration files
# 3 - Make a new migration
python manage.py makemigrations <app_name>
As mentioned in the comments and documented in similar questions, this is usually because of something dynamic in the model such as a datetime or set of choices that's coming up in an undetermined order.
The issue could also be related to a minor typo or change such as lower vs. upper case characters. In my case, my FK's model initial migration had the name set to a lowercased word rather than the proper upper case name. The referencing model was getting an alter field every time I ran makemigrations. Fixing the FK model's initial migration file by simply capitalizing the name solved the problem:
operations = [
migrations.CreateModel(
name='sentence',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
to
operations = [
migrations.CreateModel(
name='Sentence',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
Not sure how the lower case character got in there in the first place, though...
It might be a bit difficult to look through every migration file for something like this, however, so I'd recommend just removing all of your migration files, and doing a fresh makemigrations to start over from scratch.
If you'd rather not do this for some reason (migrations have already been synced to git, for example) you could move your migration files to a temporary location, run makemigrations and then see if a git diff shows anything inconsistent in your original and new initial migration files. If you're able to find the issue, restore your original migration files and fix the problem there.

django model AutoField error

I had a model like this
class Alrule(models.Model):
priority = models.PositiveIntegerField(unique=True)
rule = models.CharField(max_length=256)
I migrated this model. After I decided to make priority field as primary key with AutoField
Then my model looked like this:
class Alrule(models.Model):
priority = models.AutoField(primary_key=True)
rule = models.CharField(max_length=256)
I made a migration and migrated this change.
Now again i needed to revert back. Now I made following changes:
class Alrule(models.Model):
priority = models.PositiveIntegerField(unique=True)
rule = models.CharField(max_length=256)
I made a migration.
Now when I migrate I get the following ERROR:
AssertionError: A model can't have more than one AutoField.
My understanding is priority field was set to AutoField before and it is not removed. Please help
My first migration look like this:
operations = [
migrations.RemoveField(
model_name='alrule',
name='id',
),
migrations.AlterField(
model_name='alrule',
name='priority',
field=models.AutoField(serialize=False, primary_key=True),
),
]
Second migration looks like this:
operations = [
migrations.AddField(
model_name='alrule',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, default=2, serialize=False, verbose_name='ID'),
preserve_default=False,
),
migrations.AlterField(
model_name='alrule',
name='priority',
field=models.PositiveIntegerField(unique=True),
),
]
If you use mssql-django, there is some limitations:
The following features are currently not supported:
mssql-django does not support SQL-based regex commands
Altering a model field from or to AutoField at migration
https://github.com/microsoft/mssql-django#limitations
operations = [
migrations.AddField(
model_name='alrule',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, default=2, serialize=False, verbose_name='ID'),
preserve_default=False,
),
migrations.AlterField(
model_name='alrule',
name='priority',
field=models.PositiveIntegerField(unique=True),
),
]
Your table already has AutoField and with first operation you are adding another one.
To avoid that just swap your operations in your migration like this:
operations = [
migrations.AlterField(
model_name='alrule',
name='priority',
field=models.PositiveIntegerField(unique=True),
),
migrations.AddField(
model_name='alrule',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, default=2, serialize=False, verbose_name='ID'),
preserve_default=False,
),
]
I.e. first alter field (remove AutoField from table) and after that is done - add your id AutoField back.
That is because AutoField has not been removed just as you correctly indicated. Delete these two migration files and run makemigrations again. If it doesn't work, you might have to also delete the migration file before that and run migrations again.
As a last resort, you could just delete the migrations files apart from the init.py file. But then, I am sure it should work once you delete these two migrations and make a new migration from there.
Yes I got the simple hack of the problem. It is like this
Make the final change like this:
class Alrule(models.Model):
prioriti = models.PositiveIntegerField(unique=True)
rule = models.CharField(max_length=256)
Here priority field should be given new name ('prioriti') so that previos one gets deleted completely and a new field is created.
Now make and apply migrations.
Now again rename "prioriti" field back to "priority". And make and apply migration.
And we are done.

Django: Default value in Database, not just ORM

I would like to have a default value for a column in the database, not just the django orm.
Related ticket is in state "wontfix": https://code.djangoproject.com/ticket/470
What is the preferred way to create a default value in the relational database?
In my case it is a BooleanField which should default to FALSE.
I use PostgreSQL, but AFAIK this should not matter in this context.
I solved it like this. The file was created with manage.py makemigrations. I added only the line at the bottom.
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='State',
fields=[
('id', models.CharField(max_length=256, serialize=False, primary_key=True)),
('state', models.BooleanField(default=True)),
],
bases=(models.Model,),
),
### The following line was added
migrations.RunSQL('alter table box_state alter column state set default false')
]
You can do like this:
class MYModel(models.Model):
is_teacher = models.BooleanField(default=False)

How to fake migrations for not to create a specific existing intermediary table

I have following models
class VucutBolgesi(models.Model):
site = models.ForeignKey(Site)
bolge = models.CharField(verbose_name="Bölge", max_length=75)
hareketler = models.ManyToManyField("Hareket", verbose_name="Hareketler", null=True, blank=True, help_text="Bölgeyi çalıştıran hareketler")
class Hareket(models.Model):
site = models.ForeignKey(Site)
hareket = models.CharField(verbose_name="Hareket", max_length=75 )
bolgeler = models.ManyToManyField(VucutBolgesi, verbose_name="Çalıştırdığı Bölgeler", null=True, blank=True,
help_text="Hareketin çalıştırdığı bölgeler")
I have the same M2M on both table since I wish to display same intermediate table on both admin forms. They also have to use the same table (not create two separate tables) since one change in one admin form must be reflected to the other. Like, If I add a new Hareket to VucutBolgesi through HareketAdmin then the same result shoudl be visible on VucutBolgesiAdmin too.
For achieving this, I first remove hareketler M2M field from VucutBolgesi so Hareketler model would create the intermediate table. I migrate this and then add hareketler to VucutBolgesi with db_table attribute so it will recognize the same intermediary table.
final look of the field is as folows
hareketler = models.ManyToManyField("Hareket", verbose_name="Hareketler", db_table="antrenman_hareket_bolgeler",
null=True, blank=True, help_text="Bölgeyi çalıştıran hareketler")
When I try to migrate this, django throw following exception
django.db.utils.OperationalError: table "antrenman_hareket_bolgeler" already exists
How should I fake this migration?
Following is the migration django creates each time I run makemigrations
dependencies = [
('antrenman', '0005_vucutbolgesi_hareketler'),
]
operations = [
migrations.AddField(
model_name='vucutbolgesi',
name='hareketler',
field=models.ManyToManyField(to='antrenman.Hareket', db_table=b'antrenman_hareket_bolgeler', blank=True, help_text=b'B\xc3\xb6lgeyi \xc3\xa7al\xc4\xb1\xc5\x9ft\xc4\xb1ran hareketler', null=True, verbose_name=b'Hareketler'),
preserve_default=True,
),
]
Note: Editing related migration file and removing migrations.AddField fo not work since django creates the same migrations.AddField with each makemigrations
Is it possible to make a migration always to be faked, just override the apply and unapply methods. The consequences of this are not sufficiently investigated, but this far it works for me.
In the following example we create a migration that reuses django.contrib.auth.User.group's M2M table b'profile_user_groups:
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('profile', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='organizations',
field=models.ManyToManyField(db_column=b'group_id', db_table=b'profile_user_groups', related_name='members', to='profile.Organization'),
),
]
def apply(self, project_state, schema_editor, collect_sql=False):
return project_state.clone()
def unapply(self, project_state, schema_editor, collect_sql=False):
return project_state.clone()
Solution was so simple.
You must be sure related migration is the only migration operation that needed to be faked. You must first create the migration with
python manage.py makemigrations antrenman
Then apply that migration with --fake
python manage.py migrate --fake antrenman
Handicap is, other developers should know that they have to fake related migration. If there are others migrations alongside with this one, they should make them first and then fake this one.
It is too bad there is no parameter that tells related migration should be real or fake.