Django migration to delete rows from database - django

How can I delete rows from a database table with some criteria via a migration script?
Do I need to manually write it or generate it? How to create the file?

You need to create an empty migration file:
python manage.py makemigrations <app_label> --empty
open the generated file and add a new operation:
operations = [
migrations.RunPython(delete_some_rows) # name_of_the_function_to_be_called_to_delete_rows
]
define the function in the migration file:
def delete_some_rows(apps, scheme_editor):
model = apps.get_model('app_label', 'model_name')
model.objects.filter(...).delete()
and simply migrate.

Related

How would you create a 'manual' django migration?

I've discovered that I can set defaults for columns on a postgres database in a django project using migrations.RunSQL('some sql').
I'm currently doing this by adding a column, makemigrations, then removing the column, makemigrations, and then manually modifying the migration file that is produced.
I tried copying an old migration file and then removing the old code so just the new sql could be run and got some strange errors.
CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0067_auto_20180509_2327, 0068_auto_20180514_0707 in csmu).
To fix them run python manage.py makemigrations --merge
How would you create a 'manual' django migration?
You can create a manual migration by running the command:
python manage.py makemigrations app_name --name migration_name --empty
Where app_name corresponds to the app within your project you want to add the migration. Remember Django manages both Project and Apps (A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.)
And --empty flag is to create a migration file where you will have to add your manual migrations.
For example, on a project where you have an app named api that only has one migration file 0001_initial.py running:
python manage.py makemigrations api --name migration_example --empty
will create a file named 0002_migration_example.py under the directory api/migrations/ that will look like:
# Generated by Django 2.2.10 on 2020-05-26 20:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('api', '0001_initial'),
]
operations = [
]
And you should add migrations.RunSQL('some sql'). inside operations brackets, like:
operations = [
migrations.RunSQL('some sql')
]
You can learn how to make migrations by investigating the automatically generated migrations, for example:
class Migration(migrations.Migration):
dependencies = [
('app_details', '0001_initial'),
]
operations = [
migrations.AddField(
...,
),
migrations.CreateModel(
...,
),
migrations.RenameModel(
...,
),
migrations.RenameField(
...,
),
migrations.RemoveModel(
...,
),
# and so on
]
Create a manual migration file
use this command in the terminal: python manage.py makemigrations --empty.
Then add what you want in it.
notice: you have to compose between the "models.py" and the manual migrations.

how to switch to a new database

I want to deploy my django project to the production environments, and associated it with an new empty database, and I did as follows :
Create an new empty database
Updated settings.py and pointed the database name to the new one
Deleted the migrations folder under my App
Run python manage.py runserver and no errors returned
Run python manage.py makemigrations and python manage.py migrate
but only auth related tables created ( like auth_user , auth_group ... ), no databases tables created for my Apps
How should I do for this situation to move to the new database for my project?
Deleted the migrations folder under my App
This was your mistake, you deleted the migrations - including the initial migrations. So when you go to makemigrations you haven't got the initial migration available.
So you need to run makemigrations <app_name> to at least get the initial migration.
If you were to do this again, don't delete the migrations, just change the database settings and then migrate.
Firstly, you should not have deleted the migrations. Now, make all the migrations again which you have deleted.
python manage.py makemigrations app_name
Do this for all the apps of which you have deleted the migrations.
Now, add your new database to settings.py. Do not remove the old one yet. For example, if I were adding a MySQL database, I would have added the following to the DATABASES dictionary in settings.py:
'new': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'databasename',
'USER': 'databaseusername',
'PASSWORD': 'databasepassword',
'HOST': 'localhost',
'PORT': '3306',
}
I have named the database as 'new'. Now we have two databases 'default' and 'new'. Now you have to create tables in the new database by running the migrations on the new database:
python manage.py migrate --database=new
You can follow these additional steps if you want to transfer your data to the new database. First, clear the new database:
python manage.py flush --database=new
Now export data from the old database into a json file:
python manage.py dumpdata>data.json
Import this data into the new database:
python manage.py loaddata data.json --database=new
Now you can remove the 'default' database and rename the 'new' database to 'default'.
The procedure mentioned in this answer is taken from my blog.
Just check the output of python manage.py makemigrations command, if it is showing no change detected then you need to check that have you added that app in your INSTALLED_APPS = [] in settings.py file or it might be the problem because you have deleted migration folder.Because if is there any database connectivity error it will show you that while doing makemigrations.
If your database has a new name, i.e. not "default", you need to specify it to migrate:
python manage.py migrate --database <newdb>

How do I generate models for an existing database in Django?

I have an existing database I'd like to use with Django. Can I create models based on my existing tables?
This is documented on the Django website:
https://docs.djangoproject.com/en/3.1/howto/legacy-databases/
$ python manage.py inspectdb
You can use inspectdb command.
Like this
python manage.py inspectdb Table_Name --database=DataBaseName >
filename.py
eg: For specific table from specific database()
python manage.py inspectdb Employee_table --database=db_for_employee > models_file.py
Here db_for_employee exist in DATABASE list in settings.py file.
For specific table in default database:
python manage.py inspectdb Employee_table > models_file.py
For all the tables in default database:
python manage.py inspectdb >models_file.py
This would create a file with name models_file.py at your project level and it would contain the models for the existing database.
Note that the if you don't mention the database name then default database from the settings would be considered.
And if you don't mention the table name then all the tables from the database are considered and you'll find models for all the tables in new models.py file
Needless to say that further you'll have to copy the models or the classes created, to the actual models.py file at the application level.

django 1.7 migrate gets error "table already exists"

I am trying to apply a migration but am getting the error:
django.db.utils.OperationalError: (1050, "Table 'customers_customer'
already exists")
I get this by issuing the following command:
python manage.py migrate
My customer table already exists, so what do I do to let the migration know this, not error out, and run my modification to my model?
I ran this on my local environment with local database with no problem. It is when I pointed my database to production and ran migrate above that I get this error.
If you have the table created in the database, you can run
python manage.py migrate --fake <appname>
Mark migrations as run without actually running them
Or if you want to avoid some actions in your migration, you can edit the migration file under the app/migrations directory and comment the operations you don't want to do in the migrate execution.
Docs: https://docs.djangoproject.com/en/1.8/topics/migrations/#upgrading-from-south
or python manage.py help migrate
Its actually python manage.py migrate --fake <appname>
We can solve this issue in two way as mentioned in answer:
1.) By editing in migration file
We have migrations folder created in each application we create, In
those migration folder the migration file(0001_initial.py is the
initially created and after this all other files dependent on this
initial file will be create), When we run the python manage.py
migrate, For every APP the migration file will apply if there is
change in the file. We can see this run Applying on terminal after the
migrate command. If there is any issue in migration file we use to get
the error at that point. In my/our case:
Applying ValetUser.0002_keyroundslots_systemparameters_vehicleparking_vehicleparkingdetails...Traceback (most recent call last):
sqlite3.OperationalError: table "valet_keyroundslots" already exists
Here we can notice that the file in which we have issue is mentioned
i.e ValetUser.0002_keyroundslots_systemparameters, So we can Go to the
App and then migrations and in 0002 file we can Comment the
CreateModel Operation of That particular Model in which we are facing issue while
applying migrations.
example:
operations = [
# migrations.CreateModel(
# name='KeyRoundSlots',
# fields=[
# ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
# ('key_round', models.IntegerField()),
# ('key_slot', models.IntegerField()),
# ('is_available', models.BooleanField()),
# ('Valet_id', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='valet_location', to='ValetUser.ValetAt')),
# ],
# options={
# 'db_table': 'valet_keyroundslots',
# },
# ),
2.) By applying fake migration of the modified migration file of the particular APP in which we are facing the error/issue, --fake will
apply the fake migration that will not effect to the already applied
migration of the model.
python manage.py migrate --fake <appname>
The answers given Waqas and elmonkeylp are also right, I just wanna
explain it in brief with the help of we use to scenario

Django db Table delete

With what command can I delete tables from a django db of a specific app/ only one table?
I did find all sorts of things, but not how to get rid of a table.
Also while I am at this.
I create the models and hit syncdb and then I have the tables.
If I want to update/add to those tables, do I run into problems?
Your best bet would be to get django-south installed in your machine.
if you are using pip, do pip install django-south
This allows you too migrate data forward and backwards.
This is very handy especially if you need to update tables, and new tables etc.
check it out.
adding south to apps are as easy as python manage.py schemamigration appname --initial
Make your changes in a model and run the following python manage.py schemamigration appname --auto
Once your data migration file has been created it'll tell you data is now ready to migrate.
Simply use python manage.py migrate appname
http://south.aeracode.org/docs/about.html
Hope this helps
If you are deleting a table, this is done in the model file of the specific app that you are trying to delete, there is no command for this, you just go into the file and delete it and then re-run syncdb, for your other question, the answer is the same.. every app folder should have a file called "models.py" and here is where the models which are, in this case, equivalent to tables are specified, along with their fields, you simply edit this to make any changes.
def reset():
import install
from django.db.models import get_models
removed_tables = []
exceptions = []
for model in get_models():
if model.__name__ not in ('User','Session','Group','Permission'):
try:
model.objects.all().delete() # So we can remove the table without complaints from the database server.
CURSOR.execute('DROP TABLE %s' % model._meta.db_table)
print "Dropped table %s from model %s" % (model._meta.db_table, model.__name__)
except Exception as e:
exceptions.append([model._meta.db_table, str(e)])
continue
removed_tables.append(model._meta.db_table)
print "Removed %s tables" % len(removed_tables)
syncdb()
install.install() # A function that leads to the creation of my default data