¿Cómo saber si existen diferencias entre tus modelos Django y la base de datos?
Es posible que, por lo menos una vez en la vida, hayas tenido problemas aplicando las migraciones de tu proyecto Django.
Las migraciones son la forma en que Django propaga los cambios que realiza en sus modelos (agregar un campo, eliminar un modelo, etc.) en el esquema de su base de datos. Están diseñados para ser en su mayoría automáticos, pero necesitará saber cuándo realizar migraciones, cuándo ejecutarlas y los problemas comunes que puede encontrar. https://docs.djangoproject.com/en/3.1/topics/migrations/
¿Cuáles son los problemas más comunes?
El sistema de migraciones de Django es un sistema bastante potente. Te permite realizar varias operaciones importantes en tu base de datos, sin tan siquiera tener que escribir SQL. El sistema puede crear, a partir de los modelos que hayas creado en tus aplicaciones, toda la estructura de la base de datos, las modificaciones que realices a tus modelos se verán reflejadas en tu base de datos con tan solo escribir python manage.py makemigrations y python manage.py migrate. También te permite realizar la operación de manera contraria, creando tus modelos a partir de una base de datos ya existente. Pero, como bien lo dice el equipo de Django en su guía:
"no es perfecto y, para cambios complejos, es posible que no detecte lo que esperaba".De modo que puedas verte en la necesidad de realizar ajustes en tus modelos o en la base de datos de forma manual. El siguiente código te puede ayudar a encontrar las diferencias existentes entre tus modelos y la base de datos:
from django.db import connectionsfrom django.db.models import ForeignKey, ManyToOneRel, ManyToManyRel, ManyToManyFieldfrom django.db.utils import OperationalErrorfrom django.core.exceptions import ObjectDoesNotExistfrom django.conf import settingsdef get_cursor(db_alias="default"):"""Obtiene el cursor de la conección a la base de datos."""return connections[db_alias].cursor()def check_database():"""Compruba que la información de los modelos está acorde con la informaciónen la base de datos. Los campos que estén acordes con la información de labase de datos, serán marcados con una [X]; una casilla vacia en caso contrario [ ]."""from django.contrib.contenttypes.models import ContentTypeqs = ContentType.objects.all()cursor = get_cursor()models_evals = []dbname = str(settings.DATABASES["default"]["NAME"])text = f"=======================\nTest: {dbname}\n=======================\n"print(text)for ct in qs:model = ct.model_class()if (model is None):continuemodels_evals, text = check_model(model, cursor, models_evals, text)filename = dbname.replace("$", "_").replace(".", "_").replace(" ", "_")filename = "test/" + filename.split("/")[-1] + ".txt"f = open(filename, "w")f.write(text)f.close()print(f"Guardado en: '{filename}'")def check_model(model, cursor, models_evals=[], text=""):"""Compara la información de los campos del modelo indicado, con la base de datos."""if (str(model) in models_evals):return models_evals, textprint("\n----------------------------------")print(model, model._meta.verbose_name)text += f"\n{model} | {model._meta.verbose_name}\n"models_evals.append(str(model))try:fields = model._meta.get_fields()except (AttributeError) as e:return models_evals, textmanytomanyfieldsmodels = []for field in fields:name = field.nameif isinstance(field, ForeignKey):name = name + "_id"elif isinstance(field, ManyToManyField):manytomanyfieldsmodels.append(field.related_model)print(f"Relación: {field}")text += f"Relación: {field}\n"continueelif (isinstance(field, (ManyToOneRel, ManyToManyRel))):print(f"Dependiente: {field}")text += f"Dependiente: {field}\n"continuepri = f" - Field: {field.__class__.__name__}( '{name}' )"try:cursor.execute(f"SELECT {name} FROM {model._meta.db_table};")except (OperationalError) as e:pri = "[ ] "+ pri + f" | Error: {e}"else:pri = "[X] " + priprint(pri)text += f"{pri}\n"for many_model in manytomanyfieldsmodels:models_evals, text = check_model(many_model, cursor, models_evals, text)return models_evals, text
No hay comentarios.:
Publicar un comentario