Skip to content

Django Fixtures (Datos de prueba)

scisneros edited this page May 30, 2022 · 1 revision

Fixtures o Datos de prueba

Si han estado compartiendo su base de datos probablemente se habrán encontrado con problemas por la inconsistencia entre los datos que usa cada persona. Al testear su sistema seguramente ingresaron mucha información basura que choca con la del resto, o quizás modificaron modelos de forma paralela y al intentar unirlos pasan cosas raras con las migraciones.

Para solucionar estos problemas y tener una buena convivencia con sus datos, hablaremos sobre fixtures.

Quitar la BD del repositorio

En primer lugar, evitaremos los choques de datos y conflictos quitando la base de datos del repositorio. De esta forma cada persona siempre usará su versión local sin molestar a nadie.

Tienen que agregar db.sqlite3 a su .gitignore. Además, si ya lo tenían trackeado, tienen que eliminar su caché. Más info sobre esto en el artículo de gitignore.

Fixtures

Ahora que sus datos están independientes, necesitamos una forma de volver a centralizar los que necesitemos. Para eso creamos fixtures, que son básicamente representaciones en texto de nuestra data. Un ejemplo de fixture es:

[
  {
    "model": "users.User",
    "pk": 1,
    "fields": {
      "first_name": "Shawn",
      "last_name": "Mendes"
    }
  },
  {
    "model": "users.User",
    "pk": 2,
    "fields": {
      "first_name": "Mon",
      "last_name": "Laferte"
    }
  },
  {
      "model": "todoapp.Tareas",
      "pk": 1,
      "fields": {
        "titulo": "Hacer la tarea de PSS",
        "contenido": "segmentation fault",
        "owner": 1
      }
  }
]

Vemos que el formato es simplemente una lista de diccionarios con llave:valor, para cada instancia de objeto. En este caso, en formato JSON.

Los campos pk hacen referencia a las primary keys, o llaves primarias de cada objeto. Los campos de llave foránea (como owner), también referencian la llave primaria de la otra entidad.

Esta data puede escribirse a mano y guardarse como un archivo .json, o puede generarse automáticamente desde la data que ya existe.

Generar fixtures

Para crear fixtures utilizando la data que se encuentra actualmente en la base de datos usamos el siguiente comando:

python manage.py dumpdata -o <nombre-de-archivo>.json

También se puede especificar una app y/o modelos para el dump. Es recomendable hacerlo así o por defecto se incluirá mucha data innecesaria interna de Django.

# Incluir solo la app todoapp y categorias:
python manage.py dumpdata todoapp categorias -o <...>.json

# Incluir solo la app todoapp, pero solo el modelo Tarea:
python manage.py dumpdata todoapp.Tarea -o <...>.json

# Incluir todo excepto la app categorias y el modelo user:
python manage.py dumpdata --exclude=categorias --exclude=auth.user -o <...>.json

Para referirse a los usuarios base de Django, usa auth.user.

Cargar fixtures

Para cargar la data, ya sea creada a mano o generada con dumpdata, usamos el siguiente comando:

python manage.py loaddata <nombre-de-archivo>

Django buscará el fixture por nombre en los siguientes lugares, en este orden:

  • En todas las carpetas <app>/fixtures/ dentro de cada app.
  • En el directorio indicado en FIXTURE_DIRS en las settings.json del proyecto.
  • En la ruta indicada de forma literal en el comando.

Se instalarán todos los fixtures que coincidan con la búsqueda.

Cada vez que se use loaddata, se leerá y se instalará el fixture por completo, lo que implica que sobreescribirá la información anterior si coinciden las llaves primarias.

Uso de fixtures

Los archivos de fixture deben ir en el repositorio. De esta forma, ahora sus bases de datos quedarán independientes entre sí (por no estar sincronizadas en el repositorio), pero al mismo tiempo todos/as tendrán estos fixtures, que sirven como "instructivos" para generar data local consistente para todo el grupo.

Idealmente, que una sola persona cree la data inicial que quieran sincronizar (ya sea usando su propia interfaz o el admin de Django), y después que haga un dumpdata y haga push de los fixtures al repositorio.

Luego, sus compañeros/as hacen pull y aplican el loaddata para cada fixture, para generar la data localmente.