Revert migration on deleted not null field - django

I've got a model with a non-null field which I deleted:
class Spam(models.Model):
slug = models.SlugField(allow_unicode=True) # deleted
After I made the migrations and applied them, I wanted to revert them.
But obviously, this results in
django.db.utils.IntegrityError: NOT NULL constraint failed: eggs_spam.slug
How can I revert the migration?

There is an easier way:
Find migration where you have initially add slug field
Add default value to slug field
Unapply last migration
Remove default value from initial slug field migration

That's tricky. The only solution I can think of is the following:
1: First, create a migration that allows the slug field to be nullable
2: Then, create another migration that will populate the field for every row
3: Lastly, create a migration that makes the field non-nullable.
Hope it helps

Related

How to add in Django a non-nullable ForeignKey to an existing table?

I have the following models:
class Parent(models.Model):
name = CharField(max_length=80, ...)
class Child(models.Model):
name = CharField(max_length=80, ....)
And I want to add a non-nullable foreign key as shown here:
class Child(models.Model):
name = CharField(max_length=80, ....)
parent = ForeignKey(parent)
Both tables already exists in the database but have no data.
When running makemigrations Django asks for a default value. If I don't want to provide a default value, is it better to perform 2 migrations, the first one with null=True and then run a second one with null=False, before ingesting data in the DDBB?
Thank you for your advice.
Running two migrations would not solve anything. While running second migration you would get again warning that you have to provide a default value.
What is your intention with the existing Child instances? How do you plan to fill the parent column?
If there is no data in both the tables then it does not matter what you select to provide one-off default value just set it to 1 (in case of foreign key it works as ID, but as there is no data it does not matter).
If there is data in those tables then you have to do a 2 step migration first with null=True, then migrate data in migration script and then set it to null=False.

Is it safe to make a empty field non-empty for a existing database?

Hi, I'm trying to alter my current django project schema, the data migration tool is south. django version is 1.6.9.
It is a existing database so I don't want to mess up with my historical data.
What I'm trying to alter is making a blank=true field non-empty(blank=false)
here is my model class:
class Post(DraftableModel, EditTrackingModel):
title = models.CharField(max_length=120,
verbose_name='headline')
description = models.CharField(max_length=260,
blank=True,
verbose_name='lead-in',
help_text="260 character limit")
/*rest of the code*/
I want change the description from models.CharField(blank=True) to models.CharField(blank=False), which is the default blank value
considering the existence of my database, some of my old Post model do have empty description.
After my migration and change of database schema, will my database be corrupted?
When you try to migrate, django will warn you about those empty fields. so you have few options.
You can add a default value in your model like default="Some Default Value" and django will chose that default value for all empty fields on migration.
You can just send the migrate request and on the terminal, django will ask you to add an one-off value to be added to all the empty fields.
Also you can edit the migrate files and add different values for those empty fields based on conditions you have in mind.
You can write a function to check for all the empty fields for exiting rows and add some data based on some conditions.
Also i highly recommend to make a backup first. Doesn't matter how small the changes are or how good you are in coding.

How to save a model in django when some of the fields are populated by a sequence in oracle?

I have a model MyModel in django one of whose fields gets a value from a sequence upon insert into Oracle 12c. So I do
myModel = MyModel(field1=123,field2='abc')
myModel.save()
The problem is that field1 gets its value upon insert into the Oracle database. If I omit the field then try to save I get ORA-01400: cannot insert NULL. There's no way I can give the field a value in django, either. How do I save the model? Thanks.
Try changing your field1 to an AutoField, so every time you save a new object Oracle will assign the consecutive value.
field1 = models.AutoField()
If this is your primary key then pass the primary_key=True argument to the AutoField constructor.
UPDATE
When using legacy databases, you have to remove the mapped fields that are sequences in the database, so Django does the work of finding the way to work with those fields.

Can't migrate Django models with foreign key constraints

I have a model with a foreign key field. I want to remove the foreign key reference. However, migration fails because of the following error:
Cannot delete or update a parent row: a foreign key constraint fails
I understand what is going on, but I don't know how to resolve this properly with Django. Right now (since I'm at the beginning of my project), I go into the MySQL database manually and delete the tables and re-migrate as if it was the first migration.
Is there a way, using Django, to get around this foreign key constraint issue?
I'm using Django 1.7
Database backend is MySQL
EDIT - Models Before/After migrations
Before:
class Skills(models.Model):
# fields here...
class Project(models.Model):
skills = models.ForeignKey(Skills, verbose_name = "Required Skills", blank = True, null = True)
After:
class Skill(models.Model):
# fields here...
class Project(models.Model):
skills = models.ForeignKey(Skill, verbose_name = "Required Skills", blank = True, null = True)
I'm pretty sure all I've done is removed the "Plural" from the Skill model. The the makemigrations command works fine, but the migrate command fails with the above noted error.
EDIT 2
Hit the same error:
Cannot drop column 'skills_id': needed in a foreign key constraint 'projects_project_skills_id_4cc7e00883ac4de2_fk_projects_skill_id'
This time I dropped the field skill from model Project
A little hack I used:
Add a migration operations that first alters the field to say IntegerField before other operations i.e
operations = [
migrations.AlterField(
model_name='projects_project',
name='skills',
field=models.IntegerField(default=0)
),
..... other migration entries now after this.
]
This is my SOLUTION (do this manually first)
ALTER TABLE forms_formentry DROP FOREIGN KEY
forms_formentry_form_id_d0f23912_fk_forms_form_page_ptr_id
This is the ERROR
django.db.utils.OperationalError: (1833, "Cannot change column 'page_ptr_id': used in a foreign key constraint 'forms_formentry_form_id_d0f23912_fk_forms_form_page_ptr_id' of table 'dbname.forms_formentry'")

Using South to convert ForeignKey TO ManyToManyField not working out

I am using South to change a ForeignKey TO ManyToManyField in one of the models in Django but it is not working out as expected.
# Original Schema
class Item(models.Model):
category = models.ForeignKey(Category, default=default_category)
To be changed to
# Original Schema
class Item(models.Model):
category = models.ManyToManyField(Category, default=default_category)
So after commenting out the ForeignKey line in the model I do,
python manage.py schemamigration affected_model --auto
? The field 'Item.category' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice:
I am confused by this because 1. I have specified a default value which is "default_category" and 2. I am not removing any field I am just changing it to ManyToManyField. My question is how to go ahead in this case? Is there any other trick to make this conversion using South?
BTW I am using South 0.7 and Django 1.1.1
Thanks for the help.
In fact you are removing the field. Foreignkeys are represented by a column in your database that in that case would be named category_id. ManyToMany relationships are represented by a "through" table. With django you can either specif the through table or have one generated for you automatically.
This is a very nontrivial migration and you will need to hand code it. It will require a bit of understanding what the underlying database representation of your model is.
You will require 3 migrations to cleanly do this. First create a schemamigration with a dummy manytomany relationship to hold your data.
Then create a datamigration to copy the foreignkey relationships to your dummy manytomany
Finally create schemamigration to delete the foreignkey and rename the dummy manytomany table.
Steps 2 and 3 will both require you to manually write the migrations. I should emphasize this is a very nontrivial style of migration. However, it's entirely doable you just have to really understand what these relationships mean to the database more than your average migration. If you have little or no data it would be much simpler to just drop the tables and start over fresh with your migrations.