Está intentando agregar un campo no anulable 'new_field' al perfil de usuario sin un valor predeterminado


109

Sé que desde Django 1.7 no necesito usar South ni ningún otro sistema de migración, así que solo estoy usando un comando simple python manage.py makemigrations

Sin embargo, todo lo que obtengo es este error:

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

Aquí está models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True)
    new_field = models.CharField(max_length=140)

¿Cuáles son las opciones?


3
Quería agregar que el problema ocurre cuando se cambia la tabla existente, no cuando se crea una nueva.
x-yuri

Respuestas:


91

Debe proporcionar un valor predeterminado:

new_field = models.CharField(max_length=140, default='SOME STRING')

¿Qué sucede si necesito que new_field tenga una copia de un campo del sitio web? ¿Cómo debería verse eso? default = websiteno hace el trabajo
Irmantas Želionis

7
Que se quiere hacer en primer lugar la migración con un valor por defecto falso, a continuación, crear una migración de datos de repetición de cada registro y conjunto new_fielda website.
dgel

el valor predeterminado debe ser opcional para CharField
Florent

88

Si se encuentra en el ciclo de desarrollo inicial y no le importan los datos de su base de datos actual , simplemente puede eliminarlos y luego migrar. Pero primero debe limpiar el directorio de migraciones y eliminar sus filas de la tabla (django_migrations)

rm  your_app/migrations/*

rm db.sqlite3
python manage.py makemigrations
python manage.py migrate

8
Una cosa más. Necesita limpiar la tabla de migraciones, por ejemplo:mysql -u[user] [database] -e "delete from django_migrations where app=[your_app]"
helpse

Esta es la forma. Creo que Django apesta en la migración y la detección de modelos, etc. Quiero una actualización importante para esto.
WesternGun

Eliminé todos los archivos de las migraciones y eliminé todas las filas de django_migrations y ahora obtengo "django.db.migrations.exceptions.NodeNotFoundError: Migration stories.0001_initial dependencies reference inexistent parent node ('sources', '0002_auto_20180903_1224')" cuando se ejecuta migración.
brainLoop

1
También asegúrese de no eliminar el __init__.py de las migraciones, o de restaurarlo después, de lo contrario, las migraciones no funcionarán stackoverflow.com/a/46362750/1649917
nmu

python manage.py sqlmigrate name_of_your_app nb_of_the_migrationtambién es obligatorio
zar3bski

37

Una opción es declarar un valor predeterminado para 'new_field':

new_field = models.CharField(max_length=140, default='DEFAULT VALUE')

otra opción es declarar 'new_field' como un campo anulable:

new_field = models.CharField(max_length=140, null=True)

Si decide aceptar 'new_field' como un campo anulable, es posible que desee aceptar 'no input' como entrada válida para 'new_field'. Entonces tienes que agregar la blank=Truedeclaración también:

new_field = models.CharField(max_length=140, blank=True, null=True)

Incluso con null=Truey / o blank=Truepuede agregar un valor predeterminado si es necesario:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE', blank=True, null=True)

7
«Evite el uso de nulos en campos basados ​​en cadenas como CharField y TextField. Si un campo basado en cadenas tiene nulo = Verdadero, eso significa que tiene dos valores posibles para "sin datos": NULL y la cadena vacía ». - Referencia de campo del modelo
Chema

7

Si está al principio del ciclo de desarrollo, puede probar esto:

Eliminar / comentar ese modelo y todos sus usos. Aplicar migraciones. Eso eliminaría ese modelo y luego agregaría el modelo nuevamente, ejecutará migraciones y tendrá un modelo limpio con el nuevo campo agregado.


Y limpie la tabla de migraciones django_migrations como se describe aquí: stackoverflow.com/questions/26185687/… O simplemente use una GUI y elimine las filas requeridas.
RusI

5

En caso de que alguien esté configurando un ForeignKey, puede permitir campos que aceptan valores NULL sin establecer un valor predeterminado:

new_field = models.ForeignKey(model, null=True)

Si ya tiene datos almacenados en la base de datos, también puede establecer un valor predeterminado:

new_field = models.ForeignKey(model, default=<existing model id here>)

4

Si "sitio web" puede estar vacío new_field, entonces también debería configurarse como vacío.

Ahora, si desea agregar lógica al guardar donde new_fieldestá vacío para tomar el valor de "sitio web", todo lo que necesita hacer es anular la función de guardar para su Modelasí:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True, default='DEFAULT VALUE')
    new_field = models.CharField(max_length=140, blank=True, default='DEFAULT VALUE')

    def save(self, *args, **kwargs):
        if not self.new_field:
            # Setting the value of new_field with website's value
            self.new_field = self.website

        # Saving the object with the default save() function
        super(UserProfile, self).save(*args, **kwargs)

3

No puede agregar una referencia a la tabla que ya tiene datos dentro.
Cambio:

user = models.OneToOneField(User)

a:

user = models.OneToOneField(User, default = "")

hacer:

python manage.py makemigrations
python manage.py migrate

cambiar de nuevo:

user = models.OneToOneField(User)

hacer la migración de nuevo:

python manage.py makemigrations
python manage.py migrate

2

En new_file agregue la propiedad booleana null.

new_field = models.CharField(max_length=140, null=True)

después de ejecutar un ./manage.py syncdbpara actualizar la base de datos. y finalmente corres ./manage.py makemigrations y./manage.py migrate



2

¿Ya tiene entradas de base de datos en la tabla UserProfile? Si es así, cuando agrega nuevas columnas, la base de datos no sabe qué configurar porque no puede ser NULL. Por lo tanto, le pregunta en qué desea establecer esos campos en la columna new_fields. Tuve que eliminar todas las filas de esta tabla para resolver el problema.

(Sé que esto fue respondido hace algún tiempo, pero me encontré con este problema y esta fue mi solución. Con suerte, ayudará a cualquier persona nueva que vea esto)


1
No he insertado filas en la tabla y todavía obtengo esto. Tengo que eliminar todo el historial de migración, borrar la tabla de migración para cambiar el modelo, como sugiere Tomasz.
WesternGun

1

Honestamente, creo que la mejor manera de evitar esto fue simplemente crear otro modelo con todos los campos que necesita y con un nombre ligeramente diferente. Ejecute migraciones. Elimine el modelo no utilizado y vuelva a ejecutar las migraciones. Voila.


1

Si está de acuerdo con truncar la tabla del modelo en cuestión, puede especificar un valor predeterminado único de Noneen la solicitud. La migración será superflua default=Nonemientras que su código no tenga por defecto. Se puede aplicar muy bien porque ya no hay datos en la tabla que requerirían un valor predeterminado.


1

Estaba al principio de mi ciclo de desarrollo, por lo que puede que esto no funcione para todos (pero no veo por qué no sería así).

Agregué blank=True, null=Truea las columnas donde recibía el error. Luego ejecuté el python manage.py makemigrationscomando.

Inmediatamente después de ejecutar este comando (y antes de ejecutarlo python manage.py migrate), eliminé el blank=True, null=Truede todas las columnas. Luego corrí de python manage.py makemigrationsnuevo. Me dieron la opción de cambiar las columnas yo mismo, que seleccioné.

¡Entonces corrí python manage.py migratey todo funcionó bien!


0

Lo que Django realmente dice es:

La tabla de perfil de usuario tiene datos y puede haber new_fieldvalores que son nulos, pero no lo sé, así que ¿está seguro de que desea marcar la propiedad como no anulable, porque si lo hace, podría obtener un error si hay valores con NULL?

Si está seguro de que ninguno de los valores de la userprofiletabla es NULL, no dude e ignore la advertencia.

La mejor práctica en tales casos sería crear una migración RunPython para manejar valores vacíos como se indica en la opción 2

2) Ignore por ahora y déjeme manejar filas existentes con NULL yo mismo (por ejemplo, porque agregó una operación RunPython o RunSQL para manejar valores NULL en una migración de datos anterior)

En la migración de RunPython, debe encontrar todas las UserProfileinstancias con un new_fieldvalor vacío y poner un valor correcto allí (o un valor predeterminado como Django le pide que configure en el modelo). Obtendrá algo como esto:

# please keep in mind that new_value can be an empty string. You decide whether it is a correct value.
for profile in UserProfile.objects.filter(new_value__isnull=True).iterator():
    profile.new_value = calculate_value(profile)
    profile.save() # better to use batch save

¡Que te diviertas!


Parece que no puedo encontrar dónde está escrito esto en la documentación. ¿Pueden publicar el enlace por favor?
Cody

0

En models.py

class UserProfile(models.Model): user = models.OneToOneField(User) website = models.URLField(blank=True) new_field = models.CharField(max_length=140, default="some_value")

Necesita agregar algunos valores por defecto.


-1

Si el SSH le da 2 opciones, elija el número 1 y ponga "Ninguno". Solo eso ... por el momento.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.