Backward compatible data insertions during migrations

I found a similar thread here Backwards compatible migrations

I’m looking for advice on how data addition/deletion are typically handled with migrations.

I’m building a feature with the following scenarios

  1. some models have only new data to be inserted
  2. some models have changes like adding/deleting fields
  3. some models are new.

In all cases I need to insert new data into the table.

I identified 2 approaches to doing this. I have illustrated the approaches below with MWEs.

Approach one
Include the data inside the migration script with a function to reverse the data insertion.

models.py

from django.db import models

class NewModel(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

migration file

# migrations/000X_create_and_insert_initial_data.py
from django.db import migrations, models
import json
import os

def load_initial_data(apps, schema_editor):
    NewModel = apps.get_model('myapp', 'NewModel')
    
    # Load data from JSON file
    data_file_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'initial_data.json')
    with open(data_file_path, 'r') as f:
        initial_data = json.load(f)
    
    # Insert initial data
    for data in initial_data:
        NewModel.objects.create(**data)

def remove_initial_data(apps, schema_editor):
    NewModel = apps.get_model('myapp', 'NewModel')
    
    # Load data from JSON file
    data_file_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'initial_data.json')
    with open(data_file_path, 'r') as f:
        initial_data = json.load(f)
    
    # Collect names to remove
    initial_data_names = [item['name'] for item in initial_data]
    NewModel.objects.filter(name__in=initial_data_names).delete()
    
    # Drop the NewModel table
    schema_editor.delete_model(NewModel)

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_previous_migration'),  # Replace with your actual previous migration
    ]

    operations = [
        migrations.CreateModel(
            name='NewModel',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
                ('description', models.TextField()),
            ],
        ),
        migrations.RunPython(load_initial_data, reverse_code=remove_initial_data),
    ]

Approach Two
Use raw sql to insert/update/delete from the database tables. (Please ignore syntax errors here)

INSERT INTO TABLE mytable VALUES...

-- DROP TABLE
-- ALTER TABLE delete column
-- DELETE from table where ... ----> for deleting just new records which were inserted.

I’m trying to understand what’s the recommended practice in these scenarios and how future data additions should be handled. I would appreciate if the data migration is reversible easily since this is a critical application so we would like to avoid data inconsistencies if possible/noticed.