class Agency(models.Model):
uuid = models.UUIDField(editable=False, default=uuid.uuid4())
name = models.CharField(
verbose_name='Name',
max_length=50
)
Whenever, I am applying python manage.py makemigrations new migration files are being created. It is worth mentioning that, I am not touching models.py file.
The migration file content is.
class Migration(migrations.Migration):
dependencies = [
('dashboard', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='agency',
name='uuid',
field=models.UUIDField(default=uuid.UUID('890eb162-c485-49f0-87a6-ebc3e95a12b3'), editable=False),
),
migrations.AlterField(
model_name='agencycontract',
name='uuid',
field=models.UUIDField(default=uuid.UUID('f6500cbe-69ee-42c0-ad1e-80377f2a9dcf'), editable=False),
),
migrations.AlterField(
model_name='contractproduct',
name='uuid',
field=models.UUIDField(default=uuid.UUID('7bc66e61-c752-4333-b508-14b53c903e83'), editable=False),
),
]
I know that, hence I am using uuid function that is why those are being created. How do I stop that file creation? Before that is that really necessary to stop this migration file creation?
Use:
models.UUIDField(editable=False, default=uuid.uuid4) # Instead of uuid.uuid4()
Related
As a proof of concept, I made these two migrations in the simplest possible Django app, polls.
Here is migration 0001.
# Generated by Django 4.0.5 on 2022-06-15 18:17
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question_text', models.CharField(max_length=200)),
],
),
]
Here is migration 0002
# Generated by Django 4.0.5 on 2022-06-15 18:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('polls', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='question',
name='question_type',
field=models.CharField(max_length=200, null=True),
),
]
And here is the model.
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
question_type = models.CharField(max_length=200, null=True)
Let's say I've migrated the database, and now want to revert 0002. I run the following command python manage.py sqlmigrate polls 0002 --backwards and get this SQL
BEGIN;
--
-- Add field question_type to question
--
CREATE TABLE "new__polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL);
INSERT INTO "new__polls_question" ("id", "question_text") SELECT "id", "question_text" FROM "polls_question";
DROP TABLE "polls_question";
ALTER TABLE "new__polls_question" RENAME TO "polls_question";
COMMIT;
Clearly, it's dropping the entire column (by dropping and recreating the table), but I'm curious, could Django be made to keep that column without deleting it?
Error Message
django.db.utils.OperationalError: no such table: clientauth_tbltokentypes
What I am trying to do
I am trying to migrate data with table generation.
models.py
class tbltokentypes(models.Model):
token_type_id: AutoField(primary_key=True)
token_type: CharField(max_length=30)
I ran the command python manage.py makemigrations, which created the file 0001_initial.py.
Then in the migration file, I added managers:
from django.db import migrations, models
from clientauth.models import tbltokentypes
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='tbltokentypes',
fields=[
('token_type_id', models.AutoField(primary_key=True, serialize=False, verbose_name='token_type_id')),
('token_type', models.CharField(max_length=30)),
],
managers=[
tbltokentypes(token_type = "Registration").save()
]
)
]
Am I missing anything?
Wrap your function call in migrations.RunPython, otherwise it will be run while assigning operations, before the migration can even be run to create your table.
from django.db import migrations, models
# from clientauth.models import tbltokentypes # Remove this
# Add this function
def migrate_tbltokentypes(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
tbltokentypes = apps.get_model('clientauth', 'tbltokentypes')
tbltokentypes(token_type="Registration").save()
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='tbltokentypes',
fields=[
('token_type_id', models.AutoField(primary_key=True, serialize=False)),
('token_type', models.CharField(max_length=30)),
],
# managers=[ # Change this
# tbltokentypes(token_type = "Registration").save() #
# ] #
),
migrations.RunPython(migrate_tbltokentypes), # to this
]
Also note, from https://docs.djangoproject.com/en/3.2/topics/migrations/#data-migrations:
[Data migrations are] best written as separate migrations, sitting alongside your schema migrations.
python manage.py makemigrations --empty clientauth --name migrate_tbltokentypes
I'm trying to add internal_code to a Django Model in the existing project.
internal_code = models.CharField(max_length=128, default=uuid.uuid4, unique=True)
The problem is that when running migrate, Django raises IntegrityError:
DETAIL: Key (internal_code)=(b24f1ca6-bd90-4c91-87b0-5f246a4057e1) is duplicated.
I understand that this problem exists only during migrate as it is generated just once.
Is there a way to avoid this behavior without having to do this?:
set field to null=True
migrate
add RunPython that will populate all the existing objects internal_code fields
set field to null=False
EDIT: This is the final migration file. I want to know if I can avoid writing such migration to get the same result (automatic so not touching shell)
from django.db import migrations, models
import uuid
def gen_uuid(apps, schema_editor):
Product = apps.get_model('products', 'Product')
for product in Product.objects.all():
product.my_sku = uuid.uuid4()
product.save(update_fields=['my_sku'])
class Migration(migrations.Migration):
dependencies = [
('products', '0015_auto_20210827_1252'),
]
operations = [
migrations.AddField(
model_name='product',
name='my_sku',
field=models.CharField(max_length=128, null=True),
),
migrations.RunPython(gen_uuid),
migrations.AlterField(
model_name='product',
name='my_sku',
field=models.CharField(default=uuid.uuid4, max_length=128, unique=True),
),
]
I have a mixin to add an UUID to any model:
class UUIDable(models.Model):
uuid = UUIDField(db_index=True,
default=uuid.uuid4,
editable=False)
class Meta:
abstract = True
I have an existing database with Article objects inside.
I just added an uuid field to the Article class using the mixin above.
After running the migration, all my articles now have the SAME UUID.
I expected all the objects to have a different UUID.
Why?
Here is the automatically created migration file:
class Migration(migrations.Migration):
dependencies = [
('products', '0009_auto_20171218_1630'),
]
operations = [
migrations.AddField(
model_name='article',
name='uuid',
field=models.UUIDField(db_index=True, default=uuid.uuid4, editable=False),
),
]
Your migration is adding a singular value, and you'll need to alter it during your migration. See this link: "Migrations that add unique fields"
Try altering the field in the migration:
from django.db import migrations, models
import uuid
def create_uuid(apps, schema_editor):
Article = apps.get_model('products', 'Article')
for device in Article.objects.all():
device.uuid = uuid.uuid4()
device.save()
class Migration(migrations.Migration):
dependencies = [
('products', '0009_auto_20171218_1630'),
]
operations = [
migrations.AddField(
model_name='article',
name='uuid',
field=models.UUIDField(blank=True, null=True),
),
migrations.RunPython(create_uuid),
migrations.AlterField(
model_name='article',
name='uuid',
field=models.UUIDField(unique=True)
)
]
I am working on a Django project and made a model with several instances of a models.ForeignKey with the same Model.
class Country(models.Model):
name = models.CharField(max_length=100)
primary_language = models.ForeignKey('Language', related_name='primary_language', default="")
secondary_language = models.ForeignKey('Language', related_name='secondary_language', default="")
tertiary_language = models.ForeignKey('Language', related_name='tertiary_language', default="")
def __str__(self):
return self.name
This is the Language model:
class Language(models.Model):
name = models.CharField(max_length=50)
abbreviation = models.CharField(max_length=2)
def __str__(self):
return self.name
when doing $python3 manage.py makemigration baseit works fine, no errors.
I have put the 2 migration files I think are the most important.
class Migration(migrations.Migration):
dependencies = [
('base', '0002_country_country_code'),
]
operations = [
migrations.CreateModel(
name='Currency',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(max_length=50)),
('abbreviation', models.CharField(max_length=3)),
],
),
migrations.CreateModel(
name='Language',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('name', models.CharField(max_length=50)),
('abbreviation', models.CharField(max_length=2)),
],
),
migrations.AddField(
model_name='country',
name='phone_country_code',
field=models.CharField(default='', max_length=7),
),
migrations.AlterField(
model_name='country',
name='country_code',
field=models.CharField(default='', max_length=2),
),
migrations.AddField(
model_name='country',
name='primary_language',
field=models.ForeignKey(to='base.Language', default=''),
),
migrations.AddField(
model_name='country',
name='secondary_language',
field=models.ForeignKey(related_name='secondary_language', to='base.Language', default=''),
),
migrations.AddField(
model_name='country',
name='tertiary_language',
field=models.ForeignKey(related_name='tertiary_language', to='base.Language', default=''),
),
]
class Migration(migrations.Migration):
dependencies = [
('base', '0006_auto_20151023_0918'),
]
operations = [
migrations.AddField(
model_name='country',
name='primary_language',
field=models.ForeignKey(default='', related_name='primary_language', to='base.Language'),
),
migrations.AddField(
model_name='country',
name='secondary_language',
field=models.ForeignKey(default='', related_name='secondary_language', to='base.Language'),
),
migrations.AddField(
model_name='country',
name='tertiary_language',
field=models.ForeignKey(default='', related_name='tertiary_language', to='base.Language'),
),
migrations.AlterField(
model_name='language',
name='abbreviation',
field=models.CharField(max_length=2),
),
migrations.AlterField(
model_name='language',
name='name',
field=models.CharField(max_length=50),
),
]
Now when running the migration I get an error message I can't figure out.
I think these are the lines that matter in the stacktrace:
johan#johan-pc:~/sdp/gezelligehotelletjes_com$ python3 manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: auth, base, sessions, admin, contenttypes, hotel
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying base.0003_auto_20151023_0912...Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: column "primary_language_id" contains null values
The above exception was the direct cause of the following exception:
django.db.utils.IntegrityError: column "primary_language_id" contains null values
First of all I do not have a column "primary_language_id" but I guess this is created by Django. Even when deleting the entire Language model and the lines for the languages in the Country model, I still get this error.
Could someone help me with figuring this out?
You already have Country objects in your database.
When you add the primary_language_id column to them (which represents the primary_language ForeignKey), those countries end up with an empty primary_language (because you didn't specify a default), which throws an error (because you didn't allow empty values either for primary_language).
The solution depends on how you want that migration to work. You can add blank = True to the primary_language ForeignKey definition, add a default, or you break down your migration in 3 migrations (add the column with blank = True, set values, remove blank = True).
If you had a table created and it was populated, when you try to add it another column Django is like these data already in the table don't have this new field this guy is trying to add and it messes up. What I did was to go to my table and delete all the data. Once I did that I could migrate. If you have a small table this might work, no need to touch migrations.