Django: all identical UUIDs after migration - python

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)
)
]

Related

When reversing a Django migration with AddField, can the newly column renamed undeleted by Django?

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?

Django - add required auto-generated `uuid4` to existing project

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),
),
]

Django Migration - Migration missing some fields

This is an easy exercise, i'm a beginner about models and migration
Models.py
from django.db import models
# Create your models here.
class Flight(models.Model):
origin = models.CharField(max_length=64),
destination = models.CharField(max_length=64),
duration = models.IntegerField()
Then i'm going on my prompt and type
python manage.py makemigrations
and in migrations/0001_initial.py
# Generated by Django 3.1.7 on 2021-03-23 16:19
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Flight',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('duration', models.IntegerField()),
],
),
]
How u can see origin and destination don't migrate
How can i fix it?
remove ',' now try makemigrations
class Flight(models.Model):
origin = models.CharField(max_length=64)
destination = models.CharField(max_length=64)
duration = models.IntegerField()

Django nullable ForeignKey causes ProgrammingError

This problem is driving me nuts - I can't spot what's going on so I was hoping that someone would be able to point out what I'm missing here.
I've got two sample models, FootballClub, FootballPitch, as defined below.
class FootballClub(models.Model)
name = models.CharField(max_length=100)
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
class FootballPitch(models.Model):
name = models.CharField(max_length=100)
owning_club = models.ForeignKey(FootballClub)
I've made a modification to the FootballPitch class, more specifically the owning_club field, to add null=True to it, so the class now looks like this;
class FootballPitch(models.Model):
name = models.CharField(max_length=100)
owning_club = models.ForeignKey(FootballClub, null=True)
(I don't need to manage this model through a form so I don't care that blank=True is not set).
I have also run makemigrations and migrate on this model.
When trying to list out all instances of FootballPitch that have owning_club set to null (using FootballPitch.objects.filter(owning_club__isnull=True)) I get the following error;
Programming Error: relation "footballclub_footballpitch" does not exist
LINE 1: ...d", "footballclub_footballpitch"."name",FROM "footballclub_f...
Anyone have any ideas what is going wrong? (Django 1.8.18 and Python 2.7 and postgres 9.8 for reference)
Thanks in advance!
Edit: Due to request added migrations code here instead of in reply to comment requesting it;
./manage.py --list outputs the following;
[X] 0001_initial [X] 0002_auto_20191009_1409
The migration contains # -- coding: utf-8 -- from future import unicode_literals from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('football', '0001_initial'), ] operations = [ migrations.AlterField( model_name='footballpitch', name='owning_club', field=models.ForeignKey(to='football.FootballClub', null=True), ), ]
Edit++ to include initial migration
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
import django_extensions.db.fields
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='FootballClub',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=100)),
],
options={
'ordering': ['name'],
},
),
migrations.CreateModel(
name='FootballPitch',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=100)),
('owning_club', models.ForeignKey(to='football.FootballClub')),
],
),
]```

Django redundant migration files are being created

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()

Categories

Resources