Django migration involving RenameModel not working - django

I have been successfully using makemigrations and migrate in Django 1.7 for altering, adding and removing fields. Unfortunately, I cannot get it working when trying to rename an intermediate model. I.e. I have two models A and B, linked through a many-to-many field through model X, and I would like to rename X to Y.
Running manage.py makemigrations does not detect the rename, instead it deletes X and adds Y. But that's not the problem. I replaced Django's autogenerated scripts with:
[ migrations.RenameModel(old_name='X',new_name='Y'),
migrations.AlterField(
model_name='Y',
name='a',
field=models.ForeignKey(related_name=b'Y', to='B'),
)]
This gives me the following error:
ValueError: Lookup failed for model referenced by field b: X
So I guess it's struggling with a 'through' relation that contains the old name of the model. I tried adding a migration command to change that relation, updating it to the new name of the intermediate model, but that didn't help either.

Related

InvalidTextRepresentation: Invalid input syntax for type bigint:"All Forms"

I had a field in my model with
book_classes = (("","Select Form"),("1",'F1'),("2",'F2'),("3",'F3'),("4",'F4'),("All Forms","All Forms"))
b_classes = models.CharField('Form',max_length=9,choices=book_classes,default="n/a")
And then changed it to
b_class =models.ForeignKey(ClassBooks,on_delete=models.CASCADE)
Where
class ClassBooks(models.Model):
name = models.CharField(max_length=10)
I'm now stuck because when I try to migrate I get an error.
Invalid input syntax for type bigint:"All Forms"
Makemigrations and migrate worked well in development. When I pushed to digital ocean, the migrate returned the error stated.
What do I need to do, please?
See Foreign Key field. By default a FK field is going to use the Primary Key of the referenced table(model), in this case the id field of ClassBooks. The id field is an integer so you get the error when trying to use a string field. To make this work, from the documentation link :
ForeignKey.to_field
The field on the related object that the relation is to. By default, Django uses the primary key of the related object. If you reference a different field, that field must have unique=True.
Which in your case becomes:
b_class =models.ForeignKey(ClassBooks,to_field='name',on_delete=models.CASCADE)
This assumes that the name field has a Unique constraint on it.
Though I am not sure how "", "1", "2" ... map to ClassBooks.name.
If you dont want to lose db.sqlite3 try to delete migrations first
Step 1: Delete the db.sqlite3 file.
Step 2 : $ python manage.py migrate
Step 3 : $ python manage.py makemigrations
Step 4: Create the super user using $ python manage.py createsuperuser
new db.sqlite3 will generates automatically

Django Model Some problems

I'm Shimul,
I've been working with Django for about 1 year - but I'm having a project problem with a problem -
When I create a model - e.g.
class postmodel(models.Model):
title = models.CharField(max_length=255)
blog_slug = models.SlugField(max_length=255,unique=True)
Then I migrated the model.
after migrating my Model [blog_slug] field I want to delete.
When I migrate the model again - and then an error occurs in the database.
The error is that the field named [blog_slug] was not found,
I don't want to delete my database - I want to [blog _slug] remove it.
What can be done to avoid this problem -
If you are in development mode and you want to delete blob_slug, remove that field from models and remove database (sqlite probably), pycache files, migations documents ( do not delete migration folder and init.py files)
Then exit virtualenv and run server again.

unique_together does not replace primary key

In my Django app, I want to insert a record with a composite primary key. Apparently this should be possible by making use of "unique_together". I'm quite sure this code was working in the past, but for some reason it does not seem to be working now. This code used to run on a Linux VM, and now I'm hosting it in Google App Engine. However I don't see how this can be the cause for this error.
class TermsAndConditionsDocument(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE, verbose_name=_("Organization"))
language = models.CharField(_('Language'),choices=LANGUAGE_CHOICES, max_length=5, help_text=_("The language of the content."))
content = models.TextField()
class Meta:
unique_together = ('organization', 'language')
The error:
IntegrityError at /transactions/settings/terms_and_conditions
null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, nl-BE, <p>B</p>, 10).
According to what I've read, using "unique_together" should cause Django to not need or include an ID as primary key. I checked the database, and the ID field DOES exist. I do not understand where the database constraint and the ID field are still coming from?
Apparently, as pointed out in the comments, a primary key "id" field is always added, even if you don't need it. It's supposed to get out of your way, so you don't even notice its existence. In my case, it required me to give it a value when I created a new record, which is not how things are supposed to work.
A while back I migrated this database from one Postgres database to another Postgres database. I used an SQL dump and load method for this. Some sequences seem to have been lost during that migration.
Because there are no sequences, some fields now lacked autoincrement capabilities, explaining the IntegrityError on insertion.
In order to fix this, I did the following:
1) Export the current data:
manage.py dumpdata > data.json
2) Drop your database and create a new empty one.
3) Run database migrations:
manage.py migrate
4) Load the data again, excluding some default data already recreated by Django.
manage.py loaddata --exclude auth.permission --exclude contenttypes data.json
This procedure seems to have recreated the sequences while also keeping the data.
The unique_together only creates a DB constraint (https://docs.djangoproject.com/en/2.2/ref/models/options/#unique-together).
You could create a custom primary key with the option primary_key https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.Field.primary_key but you could only do that for one field.
But I suggest to just keep the auto increment id field, this works better with Django.
For the error are you saving a model? or doing a raw import?

Can't add new field in the django model

Django 2.0
I've created a model in Blog app,
class Category(models.Model):
field1 = models....
field2 = models....
field3 = models....
and after some time I want to add a new field in that model.
class Category(models.Model):
field1 = models....
cover_pic = .models....
field2 = models....
field3 = models....
I followed this answer. But it gives me the following error.
django.db.utils.OperationalError: (1054, "Unknown column 'blog_category.cover_pic' in 'field list'")
That answer is from 2014 and for an old Django version.
The workflow for adding new fields is simple:
Write code for the field in your model.
Run command manage.py makemigrations.
Run command manage.py migrate.
This is all in the documentation.
Since, you already followed that answer and have run the manage.py --fake command, you have messed up your db state a little bit.
To recover, do this:
Go to your "blog" app's "migration" folder.
Look at the names of the migration files. They should look like 0001_category_field1.py, 0002_category_cover_pic.py.
The faked migration will be the one with name something like 0002_category_cover_pic.py. Note its number, like 0002.
Now you'll have to move back to the previously applied migration. So, if the faked migration number is 0002, the previously applied migration will be 0001.
Now run this command - manage.py migrate --fake myapp 0001. Note the number of the migration file. You'll have to fake another migration back to the previously applied migration file.
Now run command - manage.py migrate myapp.
This should fix your problem.
If you're problem is not solved yet and you don't have important data in your database, I would suggest start your database from fresh. Delete all your database tables, then delete all the migration files inside your app_name/migration folders. Now run the two commands and start developing.
python manage.py makemigrations
python manage.py migrate
Now you will have a fresh database and you are good to go. From next time try to follow the way mentioned in the above comment.
If you are adding a new field in the Django model and after deploying to any environment , you are getting error while accessing the field.
Error:
"1054, Unknown column"
Although i also was not able to figure out how to resolve it but i came up with a work around.
I created a column manually in the DB .
I added the same field in the model.
Again tried to access the field and it worked like a charm.
I hope it helps your case.

Emptying a table and filling with fixtures

I'm working on a big project (tons of migrations already exist, etc...) and I'm at a point in which I must empty an entire table and then fill it again with ~10 elements. What is the Django approach to this situation? Fixtures? RunPython?
Deleting data from tables (Django)
A default Django-generated migration has nothing to do with populating your table. A default migration changes your database layout, e.g. creates or deletes tables, adds columns, changes parameters of columns etc. (Read until the end on how to use manual migrations to delete data from table!)
Deleting data once
What you want to do is delete entries in a table and not delete the whole table. Of course, you could remove the table from your models.py and then migrate which would delete the table (if no errors, read next) but that might result in unwanted behaviour and errors (e.g. other models have ForeignKeys to this table which would probably prevent you from deleting the table). You have two options:
Manually connect to database and run
DELETE * FROM your_table;
Use Python to do the job for you. You can open Django shell by executing python manage.py shell. Then you have to import your model and run .delete(). That would look like this:
$ python manage.py shell
# We are in Django Python shell now...
>> from app.models import Model_to_empty
>> Model_to_empty.objects.all().delete()
Deleting data from tables with manual migration files
If you want to create it as migration then you can write a migration file yourself. To make sure everything is smooth, run
python manage.py makemigrations
python manage.py migrate
first, to migrate any changes that could possible be done in between. Now, create your fake migration file like this:
If your last migration was number 0180, name your file something like 0181_manual_deletion_through_migration.py and put it in app/migrations where app is the app that contains the model that needs to be emptied and refilled.
You can use migrations.RunSQL class in your migrations which will execute statement given as argument while migrating.
Example migration file taken from one of my projects is:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('beer', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='beer',
name='beer_type',
field=models.CharField(default=0, max_length=30),
preserve_default=False,
),
]
Let's break it down:
dependencies = [
('beer', '0001_initial'),
]
This describes the previous migration that altered the model. 'beer' is the name of the app, '0001_initial' is previous migration. Set this to name of model you want to delete entries from and the name of migration should be the last migration.
operations = [
migrations.AddField(
model_name='beer',
name='beer_type',
field=models.CharField(default=0, max_length=30),
preserve_default=False,
),
]
Inside of operations comes what needs to be done. In my example, it was adding a field, thus migrations.AddField. Remember I told you about migrations.RunSQL? Well, we can use it here like this:
operations = [
migrations.RunSQL("DELETE * FROM your_model;"),
# run SQL statements to populate your model again.
]
where instead of a comment you put the SQL statements that will populate the table with entries you want.
When you finish editing the fake migration file, just execute python manage.py migrate (NO python manage.py makemigrations!!).