How can I inherit another model after creating one with models.Model, [(models.Model) ---> (BaseModel)]

Viewed 48

I created a model like this.

class BloodDiscard(models.Model):
    timestamp = models.DateTimeField(auto_now_add=True, blank=True)
    created_by = models.ForeignKey(Registration, on_delete=models.SET_NULL, null=True)
    blood_group = models.ForeignKey(BloodGroupMaster, on_delete=models.SET_NULL, null=True)
    blood_cells = models.ForeignKey(BloodCellsMaster, on_delete=models.SET_NULL, null=True)
    quantity = models.FloatField()

But now I need to apply inheritance to my model, like this. [(models.Model) ---> (BaseModel)]

class BloodDiscard(BaseModel):
    timestamp = models.DateTimeField(auto_now_add=True, blank=True)
    created_by = models.ForeignKey(Registration, on_delete=models.SET_NULL, null=True)
    blood_group = models.ForeignKey(BloodGroupMaster, on_delete=models.SET_NULL, null=True)
    blood_cells = models.ForeignKey(BloodCellsMaster, on_delete=models.SET_NULL, null=True)
    quantity = models.FloatField()

BaseModel is another model I created before but forgot to inherit it in my current model.

class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    status_master = models.ForeignKey(StatusMaster,on_delete=models.SET_NULL,default=3,null=True, blank=True)

I applied "python manage.py makemigrations" after changing (models.Model) ---> (BaseModel) and got this...

(venv) G:\office\medicover\medicover_bloodbank_django>python manage.py makemigrations
You are trying to add the field 'created_at' with 'auto_now_add=True' to blooddiscard without a default; the database needs something to populate existing rows.

 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
You can accept the default 'timezone.now' by pressing 'Enter' or you can provide another value.
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
[default: timezone.now] >>>
Migrations for 'Form':
  Form\migrations\0018_auto_20220622_2322.py
    - Add field created_at to blooddiscard
    - Add field status_master to blooddiscard
    - Add field updated_at to blooddiscard

But after that when I am applying "python manage.py migrate". I am getting this error.

(venv) G:\office\medicover\medicover_bloodbank_django>python manage.py migrate        
Operations to perform:
  Apply all migrations: Form, Master, User, admin, auth, contenttypes, sessions
Running migrations:
  Applying Form.0018_auto_20220622_2322...Traceback (most recent call last):
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.ForeignKeyViolation: insert or update on table "Form_blooddiscard" violates foreign key constraint "Form_blooddiscard_status_master_id_ffe293fa_fk_Master_st"
DETAIL:  Key (status_master_id)=(3) is not present in table "Master_statusmaster".


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\core\management\commands\migrate.py", line 244, in handle
    post_migrate_state = executor.migrate(
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\migrations\executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\migrations\migration.py", line 126, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\migrations\operations\fields.py", line 104, in database_forwards
    schema_editor.add_field(
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\base\schema.py", line 522, in add_field
    self.execute(sql, params)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\base\schema.py", line 145, in execute
    cursor.execute(sql, params)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "G:\office\medicover\medicover_bloodbank_django\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: insert or update on table "Form_blooddiscard" violates foreign key constraint "Form_blooddiscard_status_master_id_ffe293fa_fk_Master_st"
DETAIL:  Key (status_master_id)=(3) is not present in table "Master_statusmaster".

And when doing "python manage.py runserver" getting this...

(venv) G:\office\medicover\medicover_bloodbank_django>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 1 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): Form.
Run 'python manage.py migrate' to apply them.
June 22, 2022 - 23:23:51
Django version 3.2.5, using settings 'App.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

NOTE:- In StatusMaster table there's only two rows having id's 1 and 2.

2 Answers

That will not work, since BaseModel is a non-abstract model, and thus the BaseModel and the BloodDiscard share the same "primary key space": the primary key of the BloodDiscard is a ForeignKey to the BaseModel primary key.

Likely you do not want BaseModel to be a non-abstract model, but an abstract one, so you can rewrite BaseModel to:

class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    status_master = models.ForeignKey(
        StatusMaster,
        on_delete=models.SET_NULL,
        default=3,
        null=True,
        blank=True
    )

    class Meta:
        abstract = True

Remove the problematic migration file, make a new migration file, and migrate.

This is the error I was getting:-

django.db.utils.IntegrityError: insert or update on table "Form_blooddiscard" violates foreign key constraint "Form_blooddiscard_status_master_id_ffe293fa_fk_Master_st" DETAIL: Key (status_master_id)=(3) is not present in table "Master_statusmaster".

as we can see:- DETAIL: Key (status_master_id)=(3) is not present in table "Master_statusmaster".

it is telling me that in status_master, there is no "id" (PK) having the value "3".

however, in my base model:-

class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    status_master = 

models.ForeignKey(StatusMaster,on_delete=models.SET_NULL,default=3,null=True, blank=True)

someone provided a default value "3" of "status_master" which does not exist. So, I simply just removed the default value and it got solved.

Related