How to remove models from django? - django

In Django how do you remove models that you have synced into the database?
For example in Django tutorial page had this following code
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
Then I used python manage.py sql polls and python manage.py sql choice to create the tables into the database. But what if I did something wrong and don't want that model any more. What's the syntax to remove it?

If you don't want to delete and re-sync your current database, the best way is to drop the table from your model manually:
$ python manage.py dbshell
> (Inside the DB shell)
> DROP TABLE {app-name}_{model-name};

Why not simply try deleting the models from your models.py file? When you run
python manage.py makemigrations
the migrations file should be updated with the deleted models.

There is no syntax. Django doesn't removes tables or columns. You have to manually change your database or use a migration tool like South.
If you justing playing around with tutorial the easier way is to delete your sqlite database file and run a sync again.

Commenting out the class that defines the model did it for me. Once I had done it and ran python manage.py makemigrations,
I got this as response:
- Delete model MyModel.
Checked afterwards with a DB Browser and it was actually removed.

The most easiest solution is to just delete your model from models.py and run
python3 manage.py makemigrations
(Note: Remove the model from everywhere where you have imported it like admin.py, views.py, or any other file where you have imported it)

If you are facing issue to update changes onto DB so you can directly run this command.
python manage.py migrate --run-syncdb

I found a simpler method, by sheer experimentation. Even after deleting tables, Django was not making the migrations, so I did the following:
Simply delete the files created in your myapp->migrations directory, making sure that you do not delete the init.py and pycache
Starting from 001initial.py and downwards delete the files.
Run python manage.py makemigrations
Run python manage.py migrate
-M

Django’s database handling through syncdb is purely additive: any new models will be added, but deleted models will not be deleted and modified models will not be modified.
If you do not have any data you want to preserve, you are fine just dropping and recreating the database: if you have anything you want to preserve, or even if you intend to have anything you want to preserve, I cannot advise you strongly enough to use a migration tool: South has been the de facto standard for every project I’ve worked on.

Since the Migration command handle Model(database) you can do following steps.
First type
python manage.py makemigrations app_name # it will restructure your model
then type
python manage.py migrate app_name # it will apply to restructure your database.
Example:
I had Posts and PostDetail model,
later on, I wanted to remove PostDetail model and some fields(columns) from Posts model too.
I simply run migrations and migrate commands,checked in Mysql Database. It worked fine.
Hope it will work for you too.

Weather you’re removing a single model or a full app, you should first
remove the desired models from the models.py file.
Moreover, you have to make sure that no other file imports these
models or uses them (admin.py, views.py, etc).
Next, run South or migrate your database to properly delete these
models from your database.
Check the source of this information on the link below:
http://www.marinamele.com/how-to-correctly-remove-a-model-or-app-in-django

Related

Django migrations : relation already exists

I have trouble with django model migrations.
I have some models in my app, and I already have some data inside.
When I added some models in my application, and I run makemigrations, the app report that there is no change.
I know that sometimes some errors came when migrate, so I delete django_migrations table in my database and run makemigrations again, and now program found my new fields.
The problem now is that if I run migrate system tell me that some tables already exist. (Which is ok and correct, because they do). I don't want to delete those tables, because I have data already inside.
I can't run migrate --fake, because program will think that I already have all the tables, which is not true.
So, I am looking for a way to tell the program : run migration, if table exist skip it. (--fake it)
Another question is why is this happening to me, that makemigrations don't recognise my changes (some cache problems,...)?
How about doing this way ?
python manage.py makemigrations
(Skip this step if you have already have migration file ready)
It will create migrations for that package lets say with a name like 0001_initial.py
Edit the file manually so that you delete all models there except that was already created in database.
Now you do a fake migration. This will sync your database with models.
python manage.py migrate --fake
Then run makemigrations again to have rest of the tables created along with a new migration file.
python manage.py makemigrations
Regarding your other question, Why makemigrations didn't recogonize your models can be because of reasons like:
Migrations for those changes are already there in some migration file.
You missed it to mention package_name in INSTALLED_APPS but i believe you did it here.
every time you make changes to your models, try these steps :
python manage.py makemigrations [your app name]
then:
python manage.py migrate
it should work fine. but remember if you have already data(rows) in your tables you should specify the default value for each one the queries.
if not, Django prompt you to specify the default value for them
or you can just try to use blank=True or null=True in your fields like below :
website = models.URLField(blank=True)
the possible cause or this is that you have another migration in the same folder starts with the same prefix... maybe you make another migration on the same table on another branch or commit so it's saved to the db with the same prefix ie: 00010_migration_from_commit_#10, 00010_migration_from_commit_#11
the solution for this is to rename the migration file like this 00011_migration_from_commit_#11
I tried to edit the related migration file and commented the part where it creates that specific column, then ran python manage.py migrate
The main problem is the existing tables that are disabling the migration of the new tables, so the solution is straight-forward:
** Try to add managed = False to the existing dB so it won't be detected by migrate
** Redo it for all existing old tables :
class Meta:
managed=False
It sometimes gets boring when we have a lot of tables in the same application but it works perfectly!

Django Programming error column does not exist even after running migrations

I run python manage.py makemigrations and I get:
No changes detected
Then, python manage.py migrate and I get:
No migrations to apply.
Then, I try to push the changes to production:
git push heroku master
Everything up-to-date
Then, in production, I repeat the command:
heroku run python manage.py migrate
No migrations to apply.
Just in case, I run makemigrations in production:
heroku run python manage.py makemigrations
No changes detected
WHY then I get a
ProgrammingError at ....
column .... does not exist
"No changes detected" means the database is coherent with the code.
How can I debug this?¡?
I got the same problem (column not exist) but when I try to run migrate not with makemigrations (it is the same issue I believe)
Cause: I removed the migration files and replaced them with single pretending intial migration file 0001 before running the migration for the last change
Solution:
Drop tables involved in that migration of that app (consider a backup workaround if any)
Delete the rows responsible of the migration of that app from the table django_migrations in which migrations are recorded, This is how Django knows which migrations have been applied and which still need to be applied.
And here is how solve this problem:
log in as postgres user (my user is called posgres):
sudo -i -u postgres
Open an sql terminal and connect to your database:
psql -d database_name
List your table and spot the tables related to that app:
\dt
Drop them (consider drop order with relations):
DROP TABLE tablename ;
List migration record, you will see migrations applied classified like so:
id | app | name | applied
--+------+--------+---------+
SELECT * FROM django_migrations;
Delete rows of migrations of that app (you can delete by id or by app, with app don't forget 'quotes'):
DELETE FROM django_migrations WHERE app='yourapp';
log out and run your migrations merely (maybe run makemigrations in your case):
python manage.py migrate --settings=your.settings.module_if_any
Note: it is possible that in your case will not have to drop all the tables of that app and not all the migrations, just the ones of the models causing the problem.
I wish this can help.
Django migrations are recorded in your database under the 'django_migrations' table. This is how Django knows which migrations have been applied and which still need to be applied.
Have a look at django_migrations table in your DB. It may be that something went wrong when your migration was applied. So, delete the row in the table which has the migration file name that is related to that column that 'does not exist'. Then, try to re-run a migration.
Here's what i tried and it worked:
Go and add manually the column to your table
run python manage.py makemigrations
go back drop that column you added
run python manage.py migrate
I had a similar issue - the error message appeared when I clicked on the model on the django-admin site. I solved it by commenting out the field in models.py, then running migrations. Following this I uncommented the field and re ran the migrations. After that the error message disappeared.
My case might be a bit obscure, but if it helps someone, it is worth documenting here.
I was calling a function in one of my migrations, which imported a Model of said migration regularly, i.e.
from myApp.models import ModelX
The only way models should be imported in migrations would be using e.g. RunPython:
def myFunc(apps, schema_editor):
MyModel = apps.get_model('myApp 'MyModel')
and then calling that function like so:
class Migration(migrations.Migration):
operations = [
migrations.RunPython(initialize_mhs, reverse_code=migrations.RunPython.noop),
]
Additionally the original import worked until I modified the model in a later migration, making this error harder to locate.
So, I always run into this sort of problem, so today I decided to try and work it out at the database level. Thing is, I changed a model field name which Django didn't bother reflecting in a migration file. I only found out later when I ran into problems. I later looked at the migration files and discovered there was no migration for that change. But I didn't notice because I made other changes as well, so once I saw a migration file I was happy.
My advice. Create migration for each change one at a time. That way you get to see if it happened or not.
So here's my working through it in MySQL.
open mysql console.
show databases; # see all my dbs. I deleted a few
drop database <db-name>; # if needed
use <db-name>; # the database name for your django project
show tables; # see all tables in the database
DESCRIBE <table-name>; # shows columns in the database
SHOW COLUMNS FROM <db-name>; # same thing as above
ALTER TABLE <table-name> CHANGE <old-column-name> <new-column-name> <col-type>; # now I manually updated my column name
If you're using postgresql, just google the corresponding commands.
The issue was in the Models for me, for some reason Django was adding '_id' to the end of my Foreign Key column. I had to explicitly set the related named to the Foreign Key. Here 'Cards' is the parent table and 'Prices' is the child table.
class Cards(models.Model):
unique_id = models.CharField(primary_key=True, max_length=45)
name = models.CharField(max_length=225)
class Prices(models.Model):
unique_id = models.ForeignKey(Cards, models.DO_NOTHING)
Works after changing to:
class Cards(models.Model):
unique_id = models.CharField(primary_key=True, max_length=45)
name = models.CharField(max_length=225)
class Prices(models.Model):
unique_id = models.ForeignKey(Cards, models.DO_NOTHING, db_column='unique_id')
When I get this error, my extreme way to solve it is to reset my database:
Reset your database
For Postgresql on Heroku:
Heroku > your_app > Resources > database > add-ons > click on your database and open it
For postgresql
settings > Reset database
Delete all files in your_app > migrations > __pycache__ except __init.py__
Delete all files in your_app > migrations except __pycache__ folder and __init.py__
Then run:
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
type in to create your superuser, then run:
python manage.py makemigrations
python manage.py migrate
python manage.py
If you are able to inspect your models from your admin section, then it should be all okay now.
Just remove corresponding row migrations for that model in 'django_migrations' model in database.
And re run python manage.py migrate app_name
I tried all these answers with not much luck! What I did to have this problem solved with no harm was to go back through the migration files and find where the actual model was being created for the first time then manually add the field (in the column not being existed error message). Until if you run makemigrations --dry-run you get/see "No changes detected" and that worked. Basically, in my case, I had to carefully take my desired db changes back in time in proper migration file, rather creating a new migration now at the end of migration dependency chain.
Open the latest py file created after running the makemigrations command inside migrations folder of that particular app.
Inside class Migration there is a list attribute called 'operations'.
Remove the particular elements migrations.RemoveField(...).
Save and run python manage.py migrate.
A easier solution to the problem is to make your models exactly like it is in the migration first. and run python manage.py migrate.
Then revert those changes
Run
python manage.py makemigrations
python manage.py migrate
To check for which migrations are applied and which are not, use -:
python manage.py showmigrations
I solved a similar problem by deleting all migrations files (Don't forget to make a backup) and python manage.py makemigrations all of them into one clean file in development and pulling new files on the server. Before then I had dropped existing tables on the PostgreSQL.
I was getting this error for some reason when Django was looking for a column of type ForeignKey named category_id when the actual name in the database was category. I tried every Django solution I could imagine (renaming field, explicitly setting column name, etc.). I didn't want to drop tables or rows as this was a production database. The solution was simply to rename the column manually using SQL. In my case:
ALTER TABLE table_name
RENAME COLUMN category TO category_id;
Make sure you backup your database, ensure this won't break any other applications consuming that particular table, and consider having a fallback column if necessary.
What helped me in the end was simply dropping the database and creating it again as well as deleting all migrations files (including cache). (only removing migrations file didn't work for me at all)
sudo su - postgres
psql
DROP DATABASE 'yourdatabase';
CREATE DATABASE 'yourdatabase';
GRANT ALL PRIVILEGES ON DATABASE 'yourdatabase' to 'yourdjangouser';
then just
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
If you're in development and you make some examples of data that's not important, this step is beneficial for me: just flush your data, make migrations, and migrate:
python manage.py flush
python manage.py makemigrations
python manage.py migrate
After that, you may create a new database from scratch, I hope this information was helpful.
Solved this issue by running
python manage.py migrate
in Heroku Bash shell

django - schema migration - how to add a field

I have a django 1.8 app working with a db.
I'm trying to change the schema of a table using the built-in migration.
Here are the steps I did:
In my dev invironment, I grabbed the app source and ran
python manage.py sycdb
then I ran
python manage.py loaddata ~/my_data.json
then I modified modes.py. Added a field and renamed a field...all from the same table 'TABLE1' which had no data.
then
python manage.py makemigrations myapp
python manage.py migrate
Error: django.db.utils.OperationalError: table "myapp_someother_table" already exists
then ran
python manage.py migrate --fake-initial
worked!
but when I browsed to the admin page for TABLE1, I get this error:
OperationalError: no such column: myapp_table1.my_new_field_id
I checked the db and yes, there is no such column.
How can I procceed from here? I prefer to fix this via django.
If I fix it straight in the db, then the migration goes out of sync.
Migrations do not automagically see that you have made changes. Migrations detect changes by comparing the current model with the historical model saved in the migration files.
In this case, you didn't have any historical models, since you didn't have any migrations. Django was not able to detect any changes in your models, even though they were different from your database.
The correct way to make changes to your model is to first run manage.py makemigration <my_app>, and then make the changes to your model, followed by another manage.py makemigrations.
You might not be able to do it via pure django and keep your data. I don't have personal experience with south but there are a lot of mentions if this tool. Just in case if nothing else works for you...
Here is what I did to make things work, but there must be a better way so please add more answers/comments...
I deleted the sqlite db and the migration folder
I made the desired changes to model.py
ran syncdb
ran loaddata to load the json data dump that I had saved previously.
just started the dev server

Django, changed data model before app converted to south

We all love South migration in django, normally you first use convert_to_south and then make model class changes, then run schemamigration and migrate
I am not sure if the following scenario has happened to anyone, the project is not tracked under version control (git stash would be awesome), you changed the model class so much and lost the undo/redo history, and you realised the app has not yet converted to south. Is there a command to remedy this?
Here's one idea.. read all the disclaimers here first, like which databases are supported for detecting FKs.
https://docs.djangoproject.com/en/dev/ref/django-admin/#django-admin-inspectdb
Update: the real answer is to use a mix of the bottom two ideas. Basically, inspectdb is a nice human readable way to figure out the difference between your model and the database. Then, I'd manually build alter table statements to match. Luckily, sqlall outputs the create statements, so most of it will be cut and paste for new fields.
Make a backup of everything.
Copy your models.py somewhere.
Type in python manage.py inspectdb
Find the model you're looking for and paste it into the original models.py
Set up south.
Paste the new / updated models.py back into your models.py
Run schemamigration then migrate.
You can also just do the migrations manually, then convert to south.
python manage.py dbshell
Describe table (depends on your db)
Find missing rows... use alter table statements as necessary. (SQL hints in python manage.py sqlall <myapp>

How to update SQLite3 database after adding object to a Class?

I just added the num object, and tried adding it to my admin, but I get the following error: Exception Value:
no such column: game_riddle.num
Here is the class:
class Riddle(models.Model):
"""represents a riddle, comprising a question and hints"""
world = models.ForeignKey(World)
question = models.TextField()
num = models.IntegerField()
I have a small database and the last time I added the object I had to run:sqlclear and then syncdb
How can I fix my bug without clearing the database?
Read this documention: http://south.readthedocs.org/en/0.7.6/installation.html
easy_install South
After install, put 'south' in your installed_app in settings
Don't forget to sync: python manage.py syncdb
Run this command: python manage.py schemamigration app_name --auto
The migrate: python manage.py migrate
That's it. Next if you add new model or have changes. Just do step 5 and 6 and your model will be updated.
You will need to use a migration tool such as South:
South brings migrations to Django applications. Its main objectives
are to provide a simple, stable and database-independent migration
layer to prevent all the hassle schema changes over time bring to your
Django applications.