Error: Provide a one-off default now

django error

Si en alguna ocasión al trabajar con Django, y correr una migración recibes el error Provide a one-off default now, entonces este post puede serte de ayuda.

Este error, suele suceder cuando añadimos a un modelo ya existente, una nueva llave (ForeingKey), con un valor determinado.

En este post mostraré dos formas de hacerlo.

Siguiendo la documentación, Añadir una ForeignKey (non-nullable) en Django se divide en tres pasos:

Veamos primero la situación inicial:

class Post(models.Model):
    name = models.CharField(max_length=100)

Paso 1.

Primero se añade la nueva llave, donde primero definiremos null, como null=TRUE y luego desde consola correremos makemigrations().

Esto creará una nueva migración que añade el campo que hemos creado.a la tabla, por tanto ahora tenemos una nueva columna con todas sus filas con valor Null.

class Post(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, null=True, on_delete=models.CASCADE))

$ python manage.py makemigrations
Migrations for 'mi_App':
  mi_App/migrations/0002_post_category.py
    - Add field author to post

Paso 2

Ahora correremos nuevamente makemigrations, creando una una nueva migración vacía  (makemigrations --empty).

$ python manage.py makemigrations  --empty -n mi_App assign_category
Migrations for 'mi_App':
 mi_App/migrations/0003_assign_category.py

Ahora  editamos esta migración para que contenga los datos que deseamos, y es en este momento donde de acuerdo a nuestra necesidades colocaremos el valor que debe tener la nueva Foreign key.

from django.db import migrations

def assign_category(apps, schema_editor):
    Category= apps.get_model('category', 'Category')  
    Post = apps.get_model('mi_App', 'Post')               
    
    Post.objects.all().update(category=category)  # and bulk update all posts.


class Migration(migrations.Migration):

    dependencies = [...]

    operations = [
        migrations.RunPython(assign_category, migrations.RunPython.noop),
    ]

Otros posts sobre Django

Paso 3

En el tercer paso modificaremos la nueva ForeignKey en nuestro modelo, eliminando la posibilidad de valor nulo:

null=False 

class Post(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, null=False, on_delete=models.CASCADE))

Y creamos una nueva migración corriendo nuevamente makemigrations.

$ python manage.py makemigrations mi_App -n post_category_non_null

Recibirás este mensaje:

You are trying to change the nullable field 'author' on something. to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
 3) Quit, and let me add a default in models.py

Seleccionamos la opción 2 y problema resuelto.

Migrations for 'mi_App':
  something/migrations/0004_post_author_non_null.py
    - Alter field category on post

Este es el camino más largo, que sugiere la documentación, pero como siempre hay una posibilidad mas corta:

  1. En la carpeta migraciones eliminamos todas la migraciones existentes,
  2. corremos nuevamente makemigrations, con las modificaciones nuevas.
  3. corremos migrate
  4. creamos nuevamente el superusuario

Con esto quedaría resuelto.

Espero sinceramente, que esto sirva de ayuda a alguien .

……..y para cuando a ti te estén rompiendo el alma, ya el tiempo habrá cicatrizado mis heridas.

A. Torres

Un saludo

AttributeError: _io.TextIOWrapper object has no attribute  split

error en python

El error  _io.TextIOWrapper object has no attribute  split, que nos puede aparecer en Python, en alguna ocasión, suele tener una explicación sencilla.

Tal y como nos dice el propio error, el objeto no posee un atributo o método split().

Según mi experiencia, lo que sucede es que este error común cuando comenzamos , se debe a que estamos confundiendo un tipo de objeto (file), con un tipo de dato(string).

‘El objeto io.TextIOWrapper‘, es el que se obtiene cuando abrimos un documento con open() y este no ha sido leído, ni se ha escrito sobre el.  

El atributo, función o método split() corresponde a objetos de tipo string o cadenas, mientras que los objetos de tipo file, aun cuando  pueden tener un contenido de tipo texto, no son compatibles con split().

Por tanto, es a los string a los que podemos aplicarle  split(), para separar según el elemento que digamos, sus partes.

a= 'serio.jose.alberto.123.124.126' b = a.split('.') print (b)
1
a= 'serio.jose.alberto.123.124.126'
2
b = a.split('.')
3
print (b)
output:
['serio', 'jose', 'alberto', '123', '124', '126']

Hay muchas formas de dividir un objeto tipo file en partes o fragmentos.

Aquí, veremos algunos ejemplos:

Dividiendo un objeto tipo file en líneas

with open('mi_file.txt') as file:  #el metodo open ()pertenece al objeto 
                                   # file, por tanto open
                                   # siempre retorna un objeto tipo file
    mi_file = [line.rstrip('\n') for line in file]

Dividiendo segun otros elementos

Una solución que te permitirá, obtener tu objetivo, por otra vía, es convertir tu objeto file a un objeto string mediante el método read(), y luego aplicarle a este  el método split()

Veámoslo:

with open('/Volumes/Searc/testing/texto.txt','r') as file: #abrimos el objeto file 
    mi_file=file.read()  #lo leemos
    mi_div = mi_file.split(',') # le aplicamos el método split()
    print(mi_div)

La salida seria una lista con el texto dividido según comas.

output:

['Lorem ipsum dolor sit amet', ' consectetur adipiscing elit.\nCurabitur aliquet sem eget magna fermentum', ' non aliquam tortor volutpat.\nNunc pulvinar', ' dolor nec porttitor iaculis', ' diam elit finibus purus', ' et finibus ligula diam luctus erat.\nMorbi placerat sodales ligula. Aliquam iaculis congue libero', ' vel consequat tellus ullamcorper nec.\nPhasellus venenatis tempus pulvinar. Nunc nec fringilla elit. In dignissim nulla eget ligula facilisis cursus.\nVestibulum malesuada nunc sit amet turpis cursus rhoncus sollicitudin quis nisi. Sed pharetra augue nec hendrerit imperdiet.\nVestibulum volutpat dignissim nisl', ' a lobortis lacus hendrerit ut. Suspendisse ac orci felis.\nEtiam arcu tortor', ' lobortis eget commodo in', ' luctus vitae quam.\nDuis convallis', ' metus et luctus convallis', ' metus elit accumsan arcu', ' ac pretium magna justo nec ligula.\nNullam lectus arcu', ' elementum in consectetur id', ' tincidunt id justo.\nCurabitur urna nisl', ' faucibus eget ullamcorper tincidunt', ' tincidunt non ligula.\nCras mi quam', ' venenatis non suscipit vitae', ' fringilla ut tortor. Sed pellentesque turpis quis tincidunt finibus.\nNam eget volutpat metus. Duis viverra', ' mi eget egestas porta', ' purus ligula placerat nunc', ' eu finibus arcu mi eu magna.\nDonec porta lacus ut erat suscipit', ' at tincidunt mi eleifend. Quisque auctor condimentum purus', ' sit amet tempor turpis luctus ac.\nCurabitur placerat tincidunt eros ac lacinia. Curabitur malesuada hendrerit pharetra. Quisque elit ante', ' egestas quis porttitor quis', ' lacinia eu lectus. Donec dictum dictum mattis.']

Python nos permite leer el contenido de un archivo, con read.

El método read, acepta un parámetro o argumento opcional size, para leer l cierta cantidad de datos y devolverlos como una cadena (en modo de texto) o un objeto de bytes (en modo binario).

Si omites el tamaño o es negativo, Python leerá y devolverá todo el contenido del archivo; esto con archivos muy grandes puede afectar la memoria.

Read devuelve una cadena vacia si lleg al final del archivo y no puede leerlo.

Puedes ver lo métodos del objeto file aquí

Y hasta aquí, espero sinceramente que esto sirva de ayuda a alguien.

El viento hincha la vela, pero la deshilacha y hay tantas velas rotas en el fondo del mar.

J. A. Buesa