Curso Básico de Django v2

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

Si como yo te ha pasado que después de un largo tiempo de desarrollo de un sistema, te das cuenta que tus modelos pueden tener una mejor organización utilizando herencia de modelos los que ayuda a tener un código mas simple y ordenado ademas de evitar duplicar código en los modelos.

Por poner un ejemplo supongamos que tenemos tres modelos en una aplicación llamada schools (School, Student y Class)

from django.db import models

class School(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return '%s' % (self.name)


class Student(models.Model):
    name = models.CharField(max_length=20)
    school = models.ForeignKey(
        School, null=True, blank=True, on_delete=models.CASCADE
    )

    def __str__(self):
        return '%s' % (self.name)


class Class(models.Model):
    name = models.CharField(max_length=20)
    students = models.ManyToManyField(Student)

    def __str__(self):
        return '%s' % (self.name)

La aplicación tiene un año en producción (nuestros modelos tienen registros en la base de datos), por alguna razón necesitas Generar un modelo llamado People del cual heredara el modelo Student

Podríamos pensar en modificar nuestros modelos, generar migraciones y migrar de esta forma

from django.db import models

class People(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return '%s' % (self.name)


class Student(People):
    school = models.ForeignKey(
        School, null=True, blank=True, on_delete=models.CASCADE
    )

Si hacemos esto nos va a marcar este error

You are trying to add a non-nullable field 'people_ptr' to student without a default; we can't do that (the database needs something to populate existing rows).

Como Solucionamos este problema

  1. Agregamos el nuevo modelo de People y creamos las migraciones con python manage.py makemigration
class People(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return '%s' % (self.name)

Esto nos generara un archivo de migración como este

# Generated by Django 2.0.1 on 2018-10-18 23:59

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('schools', '0003_auto_20181018_1618'),
    ]

    operations = [
        migrations.CreateModel(
            name='People',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=20)),
            ],
        ),
    ]
  1. Este lo modificamos a que quede de esta forma
# Generated by Django 2.0.1 on 2018-10-18 23:59

from django.db import migrations, models

def load_info(apps, schema_editor):
    People = apps.get_model("schools", "People")
    Student = apps.get_model("schools", "Student")

    for student in Student.objects.all():
        People.objects.create(
            id=student.people_ptr,
            name=student.name,
        )


class Migration(migrations.Migration):
    atomic = False
    dependencies = [
        ('schools', '0003_auto_20181018_1618'),
    ]

    operations = [
        migrations.CreateModel(
            name='People',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=20)),
            ],
        ),
        migrations.RenameField(
            model_name='student',
            old_name='id',
            new_name='people_ptr',
        ),
        migrations.RunPython(load_info),
        migrations.RemoveField(
            model_name='student',
            name='name',
        ),
        migrations.AlterField(
            model_name='student',
            name='people_ptr',
            field=models.OneToOneField(auto_created=True, on_delete=models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='schools.People'),
        ),
    ]
  1. Modificamos nuestro modelo Student
    Quitando el campo de name y definiendo que hereda del modelo People
class Student(People):
    school = models.ForeignKey(
        School, null=True, blank=True, on_delete=models.CASCADE
    )
  1. migramos con el comando de python manage.py migrate

Con estos paso deberíamos de tener nuestros modelos funcionando.

Espero les sea útil este aporte.

Curso Básico de Django v2

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

0 Comentarios

para escribir tu comentario

Artículos relacionados