juztignoreme
juztignoreme

Reputation: 101

How do I safely delete a model field in Django?

I need to delete fields from an existing django model that already have a few objects associated with it. Deleting the fields from models.py gives me an error (obviously as there are table columns still associated with them). The data in body2 and body3 are not necessary for my app. I have copied that data from those fields to the body field. How would I go about deleting these fields without dropping the table entirely?

class Post(models.Model):
    #some fields

    body =EditorJsField(editorjs_config=editorjs_config)
    body2 =EditorJsField(editorjs_config=editorjs_config)
    body3 =EditorJsField(editorjs_config=editorjs_config)

I deleted body2 and body3 and ran migrations and when creating a new object, I get errors such as this.

django.db.utils.IntegrityError: null value in column "body2" of relation "second_posts" violates not-null constraint
DETAIL:  Failing row contains (20, Wave | Deceptiveness, and unpredictability of nature, 2021-07-19 13:40:32.274815+00, 2021-07-19 13:40:32.274815+00, {"time":1626702023175,"blocks":[{"type":"paragraph","data":{"tex..., null, null, Just how unpredictable is nature? Nature is all around us, yet, ..., image/upload/v1626702035/dfaormaooiaa8felspqd.jpg, wave--deceptiveness-and-unpredictability-of-nature, #66c77c, l, 1, 1, 0).

This is the code that I'm using to save the sanitized data(after I've deleted those fields of course.)

post = Posts.objects.create(
                body=form.cleaned_data.get('body'),
                #
            )

Upvotes: 3

Views: 15718

Answers (2)

juztignoreme
juztignoreme

Reputation: 101

Since nobody seemed to have an answer, and since it looked like this error was an anomaly, I went the non-python way and ran SQL queries and dropped the columns. For those of you who ran into the same problem,

Warning, you will lose all the data in the fields you would like to delete using this method

First, make Django aware of the changes

Delete the fields you want to be deleted and run migrations.

Before

class Post(models.Model):
    #some fields

    body =EditorJsField(editorjs_config=editorjs_config)
    body2 =EditorJsField(editorjs_config=editorjs_config)
    body3 =EditorJsField(editorjs_config=editorjs_config)

After

class Post(models.Model):
    #some fields

    body =EditorJsField(editorjs_config=editorjs_config)

Command Prompt

python manage.py makemigrations
python manage.py migrate

Drop the columns using SQL queries

First connect to your database(I used postgres). The name of the table should be something like appname_model. My app was called "Second" and the model was Post. So, the table was called second_post.

See if the columns still persist after the migrations using,

In the SQL command prompt

/d second_post

This should give you a nice diagram of the database with all the columns listed on the left side. To drop those columns, type,

ALTER TABLE second_post DROP COLUMN body2;
ALTER TABLE second_post DROP COLUMN body3;

After entering each query, the prompt should return a string ALTER TABLE if successful.

Upvotes: 6

GwynBleidD
GwynBleidD

Reputation: 20569

If you want to drop the data completely, you need to create a Django migration (using ./manage.py makemigrations preferably) that will remove those columns from the database.

Alternatively, if you want to play safe and persist the old data, you can first make those fields as nullable, then create migrations for them and at the end either just don't use them anymore or remove those columns from the model, but don't reflect it in migrations (you'll need to fake the removal of those columns in migrations though if you'll ever need to run another migration in this app).

Upvotes: 1

Related Questions