Django nos permite programar comandos internos, estos nos pueden resultar útiles para toda clase de tareas administrativas como insertar datos de forma masiva en la base de datos, realizar ciertas comprobaciones, dar de alta usuarios de forma rápida, el lÃmite es nuestra imaginación. En este artÃculo explicaré como insertar ejercicios de forma masiva leyéndolos desde un fichero de texto, esto nos ahorrará muchÃsimo tiempo ya que no tendremos que ir insertándolos uno a uno desde la interfaz de administración.
Antes de comenzar es recomendable leer los artÃculos anteriores sobre Django ya que son los pasos previos a este artÃculo:
- Django: Venv bajo FreeBSD
- Django: MVT, Apps y URLs
- Django: Modelos de base de datos
- Django: Interfaz de administración
- Django: DTL(Django Template Language)
- Django: Debug Toolbar
- Django: Registro y autenticación de usuarios
- Django: Webpack
- Django: Bootstrap mediante WebPack
- Django: Proyecto en producción
- Django: Traducciones
Como siempre activamos el venv del proyecto:
source bin/activate
cd rxWodProject/
En un artÃculo anterior ya programamos un comando de Django que dejamos crontabeado para comprobar los usuarios que se quedaban en la base de datos a medio registrar, en esa ocasión el comando se llamaba delete_limbo_users.
El siguiente comando leerá los datos de un fichero de texto y los insertará en la base de datos:
vi rxWod/management/commands/rebuild_database.py
# rebuild_database.py
from django.core.management.base import BaseCommand
import argparse
import sys
from rxWod.models import Exercise
class Command(BaseCommand):
help = 'Rebuild database from file data.'
def add_arguments(self, parser):
parser.add_argument('file_path', help='Path to exercise data file.')
def handle(self, *args, **options):
file_path = options['file_path']
print('------------------------------------')
print('| Database Rebuilder by kr0m v0.2b |')
print('------------------------------------')
# Check for duplicated ids:
exercise_ids = []
with open(file_path) as fp:
for line in fp:
line = line.strip('\n')
if line == '' or line[0] == '#':
continue
exercise_id = line.split('|')[0]
#print('exercise_id: %s' % exercise_id)
#print('exercise_ids: %s' % exercise_ids)
if exercise_id in exercise_ids:
print('+ ERROR: Cant load exercises data, duplicated ID: %s' % exercise_id)
sys.exit()
else:
exercise_ids.append(exercise_id)
# Insert data:
print('>> Populating DB with new exercises, source: %s' % file_path)
inserted_exercises = 0
with open(file_path) as fp:
for line in fp:
line = line.strip('\n')
#print('')
#print('+ Readed line: %s' % line)
if line == '' or line[0] == '#':
continue
exercise_id = line.split('|')[0]
name = line.split('|')[1]
#print('name: %s' % name)
description = line.split('|')[2]
category_id = line.split('|')[3]
level = line.split('|')[4]
default_value = line.split('|')[5]
url = line.split('|')[6]
is_metabolic = line.split('|')[7]
name_es = line.split('|')[8]
description_es = line.split('|')[9]
print('- Inserting exercise ID: %s - %s - level: %s' % (exercise_id, name, level))
# object is the retrieved or created object and created is a boolean specifying whether a new object was created
exercise, created = Exercise.objects.get_or_create(exercise_id=exercise_id)
#print('Created: %s' % created)
exercise.name = name
exercise.description = description
exercise.category_id = category_id
exercise.level = level
exercise.default_value = default_value
exercise.url = url
exercise.is_metabolic = is_metabolic
exercise.name_es = name_es
exercise.description_es = description_es
exercise.save()
inserted_exercises = inserted_exercises + 1
print('>> Inserted exercises: %i' % inserted_exercises)
print('>> Done')
Generamos el fichero de ejercicios:
# Categoris: 0 Shoulders, 1 Back, 2 Biceps, 3 Triceps, 4 Chest, 5 Core, 6 Gluteus, 7 Quadriceps, 8 Hamstring, 9 Cardio, 10 Lumbar, 11 Grip
# Levels: 0 N1, 1 N2, 2 RX, 3 RX+
# ----- CORE -----
0|Sit Ups|Sit Ups|5|0|10|https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30|True|Abdominales|Abdominales
1|Sit Ups|Sit Ups|5|1|20|https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30|True|Abdominales|Abdominales
2|Sit Ups|Sit Ups|5|2|40|https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30|True|Abdominales|Abdominales
Insertamos los datos:
------------------------------------
| Database Rebuilder by kr0m v0.2b |
------------------------------------
>> Populating DB with new exercises, source: ./exercise_data.txt
- Inserting exercise ID: 0 - Sit Ups - level: 0
- Inserting exercise ID: 1 - Sit Ups - level: 1
- Inserting exercise ID: 2 - Sit Ups - level: 2
>> Inserted exercises: 3
>> Done
Si consultamos la base de datos veremos que efectivamente han sido insertados:
su - postgres
$ psql
postgres=# \c rxwod
rxwod=# SELECT * FROM "rxWod_exercise";
id | exercise_id | name | description | default_value | category_id | level | url | is_metabolic | name_en | name_es | description_en | description_es
----+-------------+---------+-------------+---------------+-------------+-------+----------------------------------------------------------------------------------------------+--------------+---------+-------------+----------------+----------------
1 | 0 | Sit Ups | Sit Ups | 10 | 5 | 0 | https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30 | t | Sit Ups | Abdominales | Sit Ups | Abdominales
2 | 1 | Sit Ups | Sit Ups | 20 | 5 | 1 | https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30 | t | Sit Ups | Abdominales | Sit Ups | Abdominales
3 | 2 | Sit Ups | Sit Ups | 40 | 5 | 2 | https://www.youtube.com/watch?v=_HDZODOx7Zw&list=PLgve_TNgIw480TOU1ZuFiZh-zfRkRZVM6&index=30 | t | Sit Ups | Abdominales | Sit Ups | Abdominales
(3 rows)
Esto es tan solo un ejemplo, mediante este tipo de comandos podremos realizar cualquier tipo de tareas administrativas de forma rápida y sencilla.