web-dev-qa-db-fra.com

OperationalError, pas de colonne de ce type. Django

Je suis très nouveau sur Django et j'ai pu terminer le didacticiel sur djangoproject.com sans erreur. Je suis en train de parcourir le didacticiel relatif à la structure Django REST disponible à l'adresse http://www.Django-rest-framework.org/ J'en ai presque fini et j'ai simplement ajouté l'authentification. Maintenant j'obtiens:

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

J'ai cherché à plusieurs endroits sur le Web, pas seulement stackoverflow, il semble qu'en général le problème vient de ma base de données et qu'il faille le supprimer puis le refaire, je l'ai déjà fait plusieurs fois, le didacticiel m'a même supprimer la base de données et la refaire au point . Voici mon 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)

Mon 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')

Mon 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

Et enfin mon 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')),
)

Je m'excuse si j'ai posté un tas d'informations inutiles. Merci d'avance les gars.

Edition: Schéma de base de données:

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);

Après avoir creusé un peu, j’ai trouvé que lors de la suppression et de la recréation de la base de données (comme le dit le didacticiel) au lieu d’utiliser la commande makemigrations, non seulement cela n’ajoute PAS les colonnes, mais cela ne me dit pas non plus que quelque chose ne va pas, lorsqu’on exécute la commande makemigrations il me dit:

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 je commente la section highlighted dans models.py, elle affichera le même message ci-dessus mais pour la ligne owner. Donc, il veut une valeur par défaut à la fois pour highlighted et owner, mais je ne suis pas sûr de ce qu'il convient d'utiliser. De plus, le tutoriel ne m'aide pas non plus.

31
TaylorAllred

Au cours de ce didacticiel, vous avez probablement rencontré la section sur la migration, qui constituait l'un des changements majeurs de Django 1.7.

Avant Django 1.7, la commande syncdb n’apportait aucune modification susceptible de détruire les données présentes dans la base de données. Cela signifie que si vous avez synchronisé la base de données pour un modèle, puis ajouté une nouvelle ligne au modèle (une nouvelle colonne, effectivement), syncdb n'affectera pas ce changement dans la base de données.

Vous avez donc soit supprimé cette table à la main, puis exécuté à nouveau syncdb (pour le recréer à partir de zéro, en perdant toutes les données), soit vous avez entré manuellement les instructions correctes dans la base de données pour ajouter uniquement cette colonne.

Ensuite, un projet appelé south a mis en œuvre des migrations. Cela signifiait qu'il y avait un moyen de migrer en avant (et inverser, annuler) toutes les modifications apportées à la base de données et de préserver l'intégrité des données.

Dans Django 1.7, les fonctionnalités de south ont été intégrées directement dans Django. Lorsque vous travaillez avec des migrations, le processus est un peu différent.

  1. Apportez les modifications à models.py (comme d'habitude).
  2. Créez une migration. Cela génère un code pour passer de l'état actuel à l'état suivant de votre modèle. Ceci est fait avec la commande makemigrations. Cette commande est suffisamment intelligente pour détecter ce qui a changé et créera un script pour effectuer ce changement dans votre base de données.
  3. Ensuite, vous appliquez cette migration avec migrate. Cette commande applique toutes les migrations dans l'ordre.

Donc, votre syncdb normale est maintenant un processus en deux étapes, python manage.py makemigrations suivi de python manage.py migrate.

Passons maintenant à votre problème spécifique:

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)

Dans ce modèle, vous avez deux champs highlighted et code qui sont obligatoires (ils ne peuvent pas être null).

Si vous aviez ajouté ces champs depuis le début, il n'y aurait pas de problème car la table n'a pas de lignes existantes.

Toutefois, si la table a déjà été créée et que vous ajoutez un champ ne pouvant pas être nul, vous devez définir une valeur par défaut pour fournir les lignes existantes. Dans le cas contraire, la base de données n'acceptera pas vos modifications, car elles violeraient les contraintes d'intégrité des données.

C’est ce que vous demande la commande. Vous pouvez indiquer à Django d’appliquer une valeur par défaut lors de la migration ou de lui donner une valeur "vide" par défaut highlighted = models.TextField(default='') dans le modèle lui-même.

37
Burhan Khalid

Concentrons-nous sur l'erreur:

Valeur d'exception: pas de colonne de ce type: snippets_snippet.owner_id

Voyons si c'est vrai ...

Vous pouvez utiliser la commande manage.py pour accéder à votre base de données Shell (cela utilisera les variables settings.py, vous serez donc sûr de vous connecter à la bonne).

manage.py dbshell

Vous pouvez maintenant afficher les détails de votre table en tapant:

.schema TABLE_NAME

Ou dans votre cas:

.schema snippets_snippet

Vous pouvez trouver plus de commandes sqlite ici ou en envoyant un: 

.Aidez-moi

Enfin, terminez votre session en tapant:

.quitter

Cela ne vous sort pas du bois, mais vous aide à savoir sur quelle extrémité du problème il faut travailler :)

Bonne chance!

7
Gabriel Gunderson

Je vois que nous avons le même problème ici, j'ai la même erreur. Je souhaite écrire ceci pour le futur utilisateur qui rencontrera la même erreur ... Après avoir apporté des modifications au modèle de votre classe Snippet comme @Burhan Khalid, vous devez migrer les tables:

python manage.py makemigrations snippets
python manage.py migrate

Et cela devrait résoudre l'erreur . Enjoy.

6
PetarP

Cette erreur peut se produire si vous instanciez une classe qui repose sur cette table, par exemple dans views.py. 

3
marw

Le moyen le plus direct de résoudre ce type de problème consiste à suivre le processus en 3 étapes suivant:

  1. Supprimez tous les fichiers liés à la migration du dossier/répertoire de migrations de l'App (ils commencent par 0000, 0001, 0002, etc.).

  2. Supprimer/Renommer le fichier de base de données existant nommé db.sqlite3 à partir du répertoire App.

  3. Maintenant, lancez la commande suivante: 

    python manage.py migrate

    Enfin exécuter

    python manage.py createsuperuser 

    effectuer les tâches administratives (si vous le souhaitez).

2
hygull

Tiré de la réponse de Burhan Khalid et de son commentaire sur les migrations: ce qui a fonctionné pour moi a été de supprimer le contenu du dossier "migrations" avec la base de données, puis d'exécuter manage.py migrate. La suppression de la base de données n'est pas suffisante en raison des informations enregistrées sur la structure de la table dans le dossier des migrations. 

0
user3540774

Vous avez tout fait correctement, je suis passé par le même problème . D'abord, supprimez-vous la base de données et les migrations J'ai résolu l'ajout du nom de mon application dans makemigrations:

python manage.py makemigrations appname
python manage.py migrate

Cela fonctionnera certainement. 

0
Dev Jalla

D'accord avec Rishikesh. Moi aussi j'ai essayé de résoudre ce problème pendant longtemps. Cela sera résolu avec l'une des deux méthodes, ou les deux.

1. Essayez de supprimer les migrations dans le dossier de migration de l'application (sauf init . Py) puis en exécutant la commande makemigrations

2.Si cela ne fonctionne pas, essayez de renommer le modèle (ceci est le dernier recours et peut devenir un peu brouillon mais fonctionnera à coup sûr. Si Django vous demande "avez-vous renommé le modèle? Appuyez simplement sur N.") aide .. :)

0
Priyank Kodesia

J'ai fait face à ce problème et voici comment je l'ai résolu.

1) Supprimez tous les enregistrements de migration du répertoire de migration de votre application. Ce sont des fichiers nommés 0001_, 0002_, 0003_ etc. Faites attention à ne pas supprimer le fichier _init__.py.

2) Supprimez le fichier db.sqlite3. Il sera régénéré plus tard.

Maintenant, lancez les commandes suivantes:

python manage.py makemigrations appname
python manage.py migrate

Assurez-vous d'écrire le nom de votre application après makemigrations. Vous devrez peut-être créer un superutilisateur pour accéder à votre base de données à nouveau. Faites-le comme suit 

python manage.py createsuperuser
0
Mayank Khanna

Je suis aussi confronté au même problème. 

Si vous ajoutez un nouveau champ, l'erreur est indiquée car aucune colonne n'a été trouvée.

Ensuite, vous appliquez la commande make migration et ensuite la commande migrate Puis toujours la même erreur .. EX ...

 path=models.FilePathField()

Ajouter une valeur par défaut pour le champ

  path=models.FilePathField(default='')

et ensuite appliquer la commande 

  python manage.py makemigrations

  python manage.py migrate

Ça peut vous aider

0
Abhimanyu Gaurh

Si votre problème est comme le mien, voici une solution de contournement ... La bonne nouvelle est que vous ne devez pas supprimer votre base de données.

Vérifiez qu’aucun autre modèle n’utilise ce modèle comme référence. 

Django.db.utils.OperationalError: no such column: parts_part_type.blah

Cela ne m'arrivait que parce que j'avais un autre modèle appelé "produit" dans une application différente appelée "produits" qui faisait référence à ce modèle. 

part = models.ForeignKey("parts.Part", related_name="some part", limit_choices_to={'part_type':Part_Type.objects.get(prefix='PART')},)

Ma solution était:

  1. mettre en commentaire l'autre application (dans ce cas, prodcuts) de settings.py
  2. python manage.py makemigrations; python manage.py migrate
  3. commentez l'autre application afin qu'elle soit à nouveau activée.
  4. python manage.py makemigrations; python manage.py migrate

Techniquement, je pense que je dois changer la référence limit_choices_to afin 

0
SpiRail

Au départ, j'ai commenté mes nouveaux champs qui sont à l'origine de ces erreurs, puis je lance python manage.py makemigrations puis python manage.py migrate pour supprimer ces nouveaux champs. 

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')

Ensuite, je les ai récemment commentés et je lance python manage.py makemigrations et python manage.py migrate and boom. Cela a fonctionné pour moi. :)

0
Aadil Hoda