OperationalError, no hay tal columna. Django

14 minutos de lectura

Avatar de usuario de TaylorAllred
taylorallred

Soy muy nuevo en django y pude terminar el tutorial en djangoproject.com sin ningún error. Ahora estoy revisando el tutorial del marco Django REST que se encuentra en http://www.django-rest-framework.org/
Casi he terminado con él y acabo de agregar autenticación. Ahora estoy recibiendo:

OperationalError at /snippets/
no such column: snippets_snippet.owner_id
Request Method: GET
Request URL:    http://localhost:8000/snippets/
Django Version: 1.7
Exception Type: OperationalError
Exception Value:    
no such column: snippets_snippet.owner_id
Exception Location: /Users/taylorallred/Desktop/env/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py in execute, line 485
Python Executable:  /Users/taylorallred/Desktop/env/bin/python
Python Version: 2.7.5
Python Path:    
['/Users/taylorallred/Desktop/tutorial',
 '/Users/taylorallred/Desktop/env/lib/python27.zip',
 '/Users/taylorallred/Desktop/env/lib/python2.7',
 '/Users/taylorallred/Desktop/env/lib/python2.7/plat-darwin',
 '/Users/taylorallred/Desktop/env/lib/python2.7/plat-mac',
 '/Users/taylorallred/Desktop/env/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/taylorallred/Desktop/env/Extras/lib/python',
 '/Users/taylorallred/Desktop/env/lib/python2.7/lib-tk',
 '/Users/taylorallred/Desktop/env/lib/python2.7/lib-old',
 '/Users/taylorallred/Desktop/env/lib/python2.7/lib-dynload',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/taylorallred/Desktop/env/lib/python2.7/site-packages']
Server time:    Sat, 11 Oct 2014 07:02:34 +0000

He buscado en varios lugares en la web, no solo en StackOverflow para encontrar la solución, parece que, en general, el problema está en mi base de datos y necesito eliminarla y luego rehacerla, lo he hecho varias veces, el tutorial incluso me tiene elimine la base de datos y vuelva a crearla en el punto. Aquí está mi models.py:

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight


LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())



class Snippet(models.Model):
    owner = models.ForeignKey('auth.User', related_name="snippets")
    highlighted = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default="")
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES,
                                            default="python",
                                            max_length=100)
    style = models.CharField(choices=STYLE_CHOICES,
                                     default="friendly",
                                     max_length=100)
    class Meta:
        ordering = ('created',)
def save(self, *args, **kwargs):
    """
    Use the 'pygments' library to create a highlighted HTML
    representation of the code snippet.
    """
    lexer = get_lexer_by_name(self.language)
    linenos = self.linenos and 'table' or False
    options = self.title and {'title': self.title} or {}
    formatter = HtmlFormatter(style=self.style, linenos=linenos,
                                      full=true, **options)
    self.highlighted = highlight(self.code, lexer, formatter)
    super(Snippet, self).save(*args, **kwargs)

Mi serializers.py:

from django.forms import widgets
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
from django.contrib.auth.models import User



class SnippetSerializer(serializers.ModelSerializer):
    owner = serializers.Field(source="owner.username")
    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')


class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True)


    class Meta:
        model = User
        fields = ('id', 'username', 'snippets')

Mi views.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
from django.contrib.auth.models import User
from snippets.serializers import UserSerializer
from rest_framework import permissions

class SnippetList(generics.ListCreateAPIView):
    """
    List all snippets, or create a new snippet.
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    def pre_save(self, obj):
        obj.owner = self.request.user
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    """
    Retrieve, update or delete a nippet instance.
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    def pre_save(self, obj):
        obj.owner = self.request.user
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

y finalmente mi urls.py

from django.conf.urls import include
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views


urlpatterns = patterns('',
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
    url(r'^users/$', views.UserList.as_view()),
    url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
)

urlpatterns = format_suffix_patterns(urlpatterns)

urlpatterns += patterns('',
    url(r'^api-auth/', include('rest_framework.urls',
                                       namespace="rest_framework")),
)

Me disculpo si publiqué un montón de información innecesaria. Gracias de antemano chicos.

Editar: Esquema DB:

CREATE TABLE "snippets_snippet" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
"created" datetime NOT NULL, "title" varchar(100) NOT NULL, "code" text NOT NULL, 
"linenos" bool NOT NULL, "language" varchar(100) NOT NULL, "style" varchar(100) NOT NULL);

Después de investigar un poco, descubrí que al eliminar y volver a crear la base de datos (como dice el tutorial) en lugar de usar el make migrations comando, no solo NO agregaría las columnas, sino que tampoco me diría que algo estaba mal al ejecutar el make migrations comando me dice:

You are trying to add a non-nullable field 'highlighted' to snippet 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)
 2) Quit, and let me add a default in models.py

Si comento el highlighted sección en models.py publicará el mismo mensaje anterior pero para el owner línea. Así que quiere un valor predeterminado para ambos. highlighted y owner, pero no estoy seguro de qué usar. Además, el tutorial tampoco me está ayudando.

  • Si eliminó la base de datos y volvió a ejecutar syncdb, no esperaría que tuviera este problema. ¿Está seguro de que eliminó el archivo SQLite db correcto?

    – Alasdair

    11 de octubre de 2014 a las 9:57

  • Voté a favor de su pregunta, no por la pregunta en sí, sino por la minuciosidad de los detalles y la franqueza de lo que ha intentado. Las preguntas bien presentadas no son tan comunes. Desafortunadamente estoy en el móvil y no puedo dar una respuesta adecuada. Buena suerte, no obstante. Volveré a consultar más tarde para ver cómo van las cosas.

    – skzryzg

    11/10/2014 a las 13:46

  • No sabía que podría estar eliminando la base de datos incorrecta. ejecuto el comando rm tmp.db y entonces python manage.py syncdb cada vez que lo hago, me pide que cree un superusuario, lo cual hago. Hago esto en la misma pestaña de terminal que he hecho el resto del proyecto mientras también estoy en el mismo entorno.

    – Taylor Allred

    11/10/2014 a las 18:43


  • Entonces, ¿alguien más tiene una posible solución?

    – Taylor Allred

    12 de octubre de 2014 a las 5:34

  • Yo también tuve esto, no pude resolverlo. Clonar el git del tutorial y ejecutar la sincronización parece crear el campo id_propietario en sqllite, pero no pude hacer que lo hiciera siguiendo el tutorial.

    – n4cer500

    13/10/2014 a las 22:04

Avatar de usuario de Burhan Khalid
burhan khalid

A medida que avanzaba en el tutorial, debe haber encontrado la sección sobre migración, ya que este fue uno de los principales cambios en Django 1.7.

Antes de Django 1.7, el comando syncdb nunca hizo ningún cambio que tuviera la posibilidad de destruir los datos actualmente en la base de datos. Esto significaba que si sincronizaba un modelo y luego agregaba una nueva fila al modelo (una nueva columna, efectivamente), syncdb no afectaría ese cambio en la base de datos.

Entonces, o soltó esa tabla a mano y luego ejecutó syncdb nuevamente (para recrearla desde cero, perdiendo cualquier dato), o ingresó manualmente las declaraciones correctas en la base de datos para agregar solo esa columna.

Entonces surgió un proyecto llamado south que implementó migraciones. Esto significaba que había una manera de migrar hacia adelante (y revertir, deshacer) cualquier cambio en la base de datos y preservar la integridad de los datos.

En Django 1.7, la funcionalidad de south se integró directamente en Django. Cuando se trabaja con migraciones, el proceso es un poco diferente.

  1. Hacer cambios a models.py (como normal).
  2. Crear una migración. Esto genera código para pasar del estado actual al siguiente estado de su modelo. Esto se hace con el makemigrations dominio. Este comando es lo suficientemente inteligente como para detectar qué ha cambiado y creará una secuencia de comandos para efectuar ese cambio en su base de datos.
  3. A continuación, aplica esa migración con migrate. Este comando aplica todas las migraciones en orden.

Así que tu normal syncdb ahora es un proceso de dos pasos, python manage.py makemigrations seguido por python manage.py migrate.

Ahora, a su problema específico:

class Snippet(models.Model):
    owner = models.ForeignKey('auth.User', related_name="snippets")
    highlighted = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default="")
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES,
                                            default="python",
                                            max_length=100)
    style = models.CharField(choices=STYLE_CHOICES,
                                     default="friendly",
                                     max_length=100)

En este modelo, tienes dos campos. highlighted y code que se requiere (no pueden ser nulos).

Si hubiera agregado estos campos desde el principio, ¿no habría ningún problema porque la tabla no tiene filas existentes?

Sin embargo, si la tabla ya se creó y agrega un campo que no puede ser nulo, debe definir un valor predeterminado para proporcionar filas existentes; de lo contrario, la base de datos no aceptará sus cambios porque violarían las restricciones de integridad de datos. .

Esto es lo que le indica el comando. Puede decirle a Django que aplique un valor predeterminado durante la migración, o puede darle un valor predeterminado “en blanco” highlighted = models.TextField(default="") en el modelo mismo.

  • Sin embargo, lo que dice tiene sentido, ¿no debería solucionar el problema si elimino la tabla? Dado que estaría recreando la tabla, esos campos estarían allí desde el principio, ¿verdad? Pero en la práctica (al menos cuando lo hago, creo que lo estoy haciendo bien…) sigue sin funcionar, ahora sin embargo, cuando ejecuto el makemigrations comando dice que todo está bien y “no se detectaron cambios”, pero cuando entro en el shell y miro el esquema db todavía no muestra el owner o highlighted campos.

    – Taylor Allred

    14 de octubre de 2014 a las 6:38

  • Si eliminó la tabla, debe volver a migrar. Debería haber una carpeta llamada migraciones en su aplicación, vea cuántas migraciones hay.

    – Burhan Jalid

    14 de octubre de 2014 a las 9:37

  • Sin embargo, el tutorial indica que se debe eliminar el archivo sqlite y ejecutar syncdb para volver a crearlo. Incluso en este caso, el campo no se creó en la tabla snippets_snippet.

    – n4cer500

    14/10/2014 a las 13:43

  • Así que actualmente mis campos en mi modelo se ven como owner = models.ForeignKey('auth.User', related_name='snippets') y highlighted = models.TextField() ¿Deberían verse como owner = models.ForeignKey('auth.User', related_name='snippets', default='') y highlighted = models.TextField(default='') ?

    – Taylor Allred

    14/10/2014 a las 23:29

  • Ok, hasta ahora, parece estar funcionando, completé los cambios en los campos que tenía en el comentario anterior publicado. En el mínimo, me permite continuar con el tutorial y no me da errores, todavía no estoy 100% seguro de si esto solucionó completamente el problema, pero hasta ahora todo bien. Si me encuentro con más problemas en el camino que coincidan con este problema, publicaré una actualización aquí; de lo contrario, si tengo otro problema que no puedo resolver, publicaré otra pregunta. ¡Gracias por la ayuda a todos!

    – Taylor Allred

    15 de octubre de 2014 a las 3:52

Paso 1: elimine el archivo db.sqlite3.

Paso 2: $ python manage.py migrar

Paso 3: $ python manage.py makemigrations

Paso 4: Cree el superusuario usando $ python manage.py createsuperuser

el nuevo db.sqlite3 se generará automáticamente

  • me salvaste la vida jaja gracias

    usuario10719814

    25 oct 2021 a las 21:11

  • Me salvaste con el paso 1. Esto db.sqlite3 era la razón de todos mis problemas.

    – Momento

    27 abr a las 13:31

  • tengo que especificar python manage.py makemigrations snippets

    –Shiv Krishna Jaiswal

    11 de junio a las 14:48

  • Esto solucionó mi problema jajaja >>> Paso 1: Eliminar el archivo db.sqlite3.

    – Shashi123

    21 de agosto a las 1:33

  • ¿Esta solución está relacionada solo con Sqlite3? ¿Y si estamos en producción con PostgreSQL? En este caso, eliminar toda la base de datos no parece una gran idea.

    – usuario840718

    13 oct a las 13:13

Centrémonos en el error:

Valor de excepción: no existe tal columna: snippets_snippet.owner_id

A ver si eso es cierto…

Puede usar el comando manage.py para acceda a su shell de base de datos (esto usará las variables settings.py, por lo que seguramente se conectará a la correcta).

manage.py dbshell

Ahora puede mostrar los detalles de su tabla escribiendo:

.schema TABLE_NAME

O en tu caso:

.schema snippets_snippet

Se pueden encontrar más comandos sqlite aquí o emitiendo un:

.help

Por último, termine su sesión escribiendo:

.quit

Esto no lo saca del bosque, pero lo ayuda a saber en qué parte del problema trabajar 🙂

¡Buena suerte!

  • Muchas gracias por mostrarme cómo acceder al shell sqlite (o cualquier shell que esté configurado)… muy impresionante y no sé por qué no aprendí sobre esto antes… ¡Gracias!

    – twknab

    13 mayo 2017 a las 11:27

avatar de usuario de copser
copser

Veo que tenemos el mismo problema aquí, tengo el mismo error. Quiero escribir esto para el futuro usuario que experimentará el mismo error. Después de realizar cambios en su modelo de Fragmento de clase como dijo @Burhan Khalid, debe migrar las tablas:

python manage.py makemigrations snippets
python manage.py migrate

Y eso debería resolver el error. Disfrutar.

Este error puede ocurrir si crea una instancia de una clase que se basa en esa tabla, por ejemplo, en views.py.

  • muy útil – Te daría muchos más +1 si pudiera. Estoy practicando con la creación de objetos con modelos Django y había creado instancias de algunas instancias de clase manualmente en views.pyen lugar de enviar un formulario, etc. Una vez que eliminé estos eventos de creación, pude makemigrations y migrate sin el django.db.utils.OperationalError: table {{project}}_{{app}} has no column named {{field_trying_to_add}} error. ¡Gracias!

    – twknab

    12 de mayo de 2017 a las 7:12

  • Puedes explicarme mas ?

    –Istiaque Ahmed

    12 de junio de 2018 a las 5:40

  • @istiaque-ahmed Este error me sucedió cuando estaba instanciando una clase con un modelo en el nivel de toda la aplicación. El mecanismo de migración no pudo verificar los atributos en el tiempo de ejecución y no pudo ejecutar los cambios para el modelo/tabla en particular.

    – tuétano

    12 de junio de 2018 a las 10:08

Inicialmente, he comentado mis nuevos campos que están causando esos errores y ejecuto python manage.py hacer migraciones y entonces python manage.py migrar para eliminar realmente esos nuevos campos.

class FootballScore(models.Model):
    team = models.ForeignKey(Team, related_name="teams_football", on_delete=models.CASCADE)
    # match_played = models.IntegerField(default="0")
    # lose = models.IntegerField(default="0")
    win = models.IntegerField(default="0")
    # points = models.IntegerField(default="0")

class FootballScore(models.Model):
    team = models.ForeignKey(Team, related_name="teams_football", on_delete=models.CASCADE)
    match_played = models.IntegerField(default="0")
    lose = models.IntegerField(default="0")
    win = models.IntegerField(default="0")
    points = models.IntegerField(default="0")

Luego los descomenté y ejecuté python manage.py hacer migraciones y python manage.py migrar y bum. Funcionó para mí. 🙂

  • muy útil – Te daría muchos más +1 si pudiera. Estoy practicando con la creación de objetos con modelos Django y había creado instancias de algunas instancias de clase manualmente en views.pyen lugar de enviar un formulario, etc. Una vez que eliminé estos eventos de creación, pude makemigrations y migrate sin el django.db.utils.OperationalError: table {{project}}_{{app}} has no column named {{field_trying_to_add}} error. ¡Gracias!

    – twknab

    12 de mayo de 2017 a las 7:12

  • Puedes explicarme mas ?

    –Istiaque Ahmed

    12 de junio de 2018 a las 5:40

  • @istiaque-ahmed Este error me sucedió cuando estaba instanciando una clase con un modelo en el nivel de toda la aplicación. El mecanismo de migración no pudo verificar los atributos en el tiempo de ejecución y no pudo ejecutar los cambios para el modelo/tabla en particular.

    – tuétano

    12 de junio de 2018 a las 10:08

Avatar de usuario de Mayank Khanna
Mayank Khanna

Me enfrenté a este problema y así es como lo resolví.

1) Elimine todos los registros de migración del directorio de migración de su aplicación. Estos son archivos llamados 0001_,0002_,0003_ etc. Tenga cuidado de no borrar el archivo _init__.py.

2) Elimine el archivo db.sqlite3. Será regenerado más tarde.

Ahora, ejecute los siguientes comandos:

python manage.py makemigrations appname
python manage.py migrate

Asegúrese de escribir el nombre de su aplicación después de realizar migraciones. Es posible que deba crear un superusuario para acceder nuevamente a su base de datos. Hazlo de la siguiente manera

python manage.py createsuperuser

  • Gracias por indicar que el nombre de la aplicación también es necesario al realizar migraciones. Esto ayudó

    – Amresh Giri

    18 de agosto de 2020 a las 18:16

¿Ha sido útil esta solución?