Django REST框架教程,OperationalError:table snippets_snippet没有名为owner_id的列

时间:2016-04-09 12:41:49

标签: django sqlite django-rest-framework

在我得到显而易见的响应之前,关于检查数据库本身,我首先会说我已经检查了this post,它与我的设置几乎相同,以及删除的解决方案正如预期的那样,数据库和迁移以及在表中添加默认值都不起作用。但是,我确实希望解决方案非常简单。

那就是说,我正在做the tutorial for django-rest-framework而我的问题始于part 4。教程如下:

  

现在,如果再次打开浏览器并刷新页面,您会在页面右上方看到“登录”链接。如果您以之前创建的某个用户身份登录,则可以再次创建代码段。

     

创建一些代码段后,导航到'/ users /'   端点,并注意该表示包括一个列表   每个用户的每个用户关联的代码段pks   'snippets'字段。

因此,我尝试使用manage.py shell创建“snippets”对象,如本教程的第一部分所示,使用以下代码:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer

snippet = Snippet(code='foo = "bar"\n')
snippet.save()

这就是结束的地方。 .save()触发错误,我在下面打印了回溯。

使用之前回答的问题的建议,我稍微改变了我的设置,但我仍然收到错误。这是设置:

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(default='')
    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):
        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)

serializers.py:

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.ReadOnlyField(source='owner.username')

    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')


class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

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

views.py:

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


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    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

/snippets/urls.py

from django.conf.urls import url, include
from snippets.views import SnippetList, SnippetDetail, UserList, UserDetail
from rest_framework.urlpatterns import format_suffix_patterns


urlpatterns = [

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

]

urlpatterns = format_suffix_patterns(urlpatterns)
urlpatterns += [
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
]

urls.py:

from django.conf.urls import url, include

urlpatterns = [
    url(r'^', include('snippets.urls')),
]

,最后,丑陋的追溯:

In [6]: snippet.save()
    ---------------------------------------------------------------------------
    OperationalError                          Traceback (most recent call last)
    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\utils.py in execute(self, sql, params)
         63             else:
    ---> 64                 return self.cursor.execute(sql, params)
         65

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\sqlite3\base.py in execute(self, query, params)
        322         query = self.convert_query(query)
    --> 323         return Database.Cursor.execute(self, query, params)
        324

    OperationalError: table snippets_snippet has no column named owner_id

    The above exception was the direct cause of the following exception:

    OperationalError                          Traceback (most recent call last)
    <ipython-input-6-fe28bd3dc796> in <module>()
    ----> 1 snippet.save()

    D:\GitHub Repositories\Django\tutorial\snippets\models.py in save(self, *args, **kwargs)
         34                                   full=True, **options)
         35         self.highlighted = highlight(self.code, lexer, formatter)
    ---> 36         super(Snippet, self).save(*args, **kwargs)

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base.py in save(self, force_insert, force_update, using, update_fields)
        698
        699         self.save_base(using=using, force_insert=force_insert,
    --> 700                        force_update=force_update, update_fields=update_fields)
        701     save.alters_data = True
        702

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base.py in save_base(self, raw, force_insert, force_update, using, update_fields)
        726             if not raw:
        727                 self._save_parents(cls, using, update_fields)
    --> 728             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
        729         # Store the database on which the object was saved
        730         self._state.db = using

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base.py in _save_table(self, raw, cls, force_insert, force_update, using, update_fields)
        810
        811             update_pk = bool(meta.has_auto_field and not pk_set)
    --> 812             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
        813             if update_pk:
        814                 setattr(self, meta.pk.attname, result)

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base.py in _do_insert(self, manager, using, fields, update_pk, raw)
        849         """
        850         return manager._insert([self], fields=fields, return_id=update_pk,
    --> 851                                using=using, raw=raw)
        852
        853     def delete(self, using=None, keep_parents=False):

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)
        120         def create_method(name, method):
        121             def manager_method(self, *args, **kwargs):
    --> 122                 return getattr(self.get_queryset(), name)(*args, **kwargs)
        123             manager_method.__name__ = method.__name__
        124             manager_method.__doc__ = method.__doc__

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\query.py in _insert(self, objs, fields, return_id, raw, using)
       1037         query = sql.InsertQuery(self.model)
       1038         query.insert_values(fields, objs, raw=raw)
    -> 1039         return query.get_compiler(using=using).execute_sql(return_id)
       1040     _insert.alters_data = True
       1041     _insert.queryset_only = False

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\sql\compiler.py in execute_sql(self, return_id)
       1058         with self.connection.cursor() as cursor:
       1059             for sql, params in self.as_sql():
    -> 1060                 cursor.execute(sql, params)
       1061             if not (return_id and cursor):
       1062                 return

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\utils.py in execute(self, sql, params)
         77         start = time()
         78         try:
    ---> 79             return super(CursorDebugWrapper, self).execute(sql, params)
         80         finally:
         81             stop = time()

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\utils.py in execute(self, sql, params)
         62                 return self.cursor.execute(sql)
         63             else:
    ---> 64                 return self.cursor.execute(sql, params)
         65
         66     def executemany(self, sql, param_list):

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\utils.py in __exit__(self, exc_type, exc_value, traceback)
         93                 if dj_exc_type not in (DataError, IntegrityError):
         94                     self.wrapper.errors_occurred = True
    ---> 95                 six.reraise(dj_exc_type, dj_exc_value, traceback)
         96
         97     def __call__(self, func):

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\utils\six.py in reraise(tp, value, tb)
        683             value = tp()
        684         if value.__traceback__ is not tb:
    --> 685             raise value.with_traceback(tb)
        686         raise value
        687

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\utils.py in execute(self, sql, params)
         62                 return self.cursor.execute(sql)
         63             else:
    ---> 64                 return self.cursor.execute(sql, params)
         65
         66     def executemany(self, sql, param_list):

    C:\Users\Jordon\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\sqlite3\base.py in execute(self, query, params)
        321             return Database.Cursor.execute(self, query)
        322         query = self.convert_query(query)
    --> 323         return Database.Cursor.execute(self, query, params)
        324
        325     def executemany(self, query, param_list):

    OperationalError: table snippets_snippet has no column named owner_id

2 个答案:

答案 0 :(得分:1)

首先,在保存Snippet对象时,您没有为“所有者”提供值。你需要做这样的事情:

from django.contrib.auth.models import User
new_user = User.objects.create(...)
snippet = Snippet(owner=new_user, code='foo = "bar"\n')
snippet.save()

尽管如此,它并没有解释为什么没有创建owner_id列。您能否将模型更改为此类型,并查看它是否检测到所有者列?

from django.contrib.auth.models import User

class Snippet(models.Model):
    owner = models.ForeignKey(User, related_name='snippets')
    ...

然后运行这些步骤以尝试创建列。

python manage.py makemigrations snippets
python manage.py migrate

答案 1 :(得分:0)

看起来你没有删除原始数据库。

教程在模型更改后将其删除:

rm -f tmp.db db.sqlite3
rm -r snippets/migrations
python manage.py makemigrations snippets
python manage.py migrate

如果你没有删除tmp.db或db.sqlite3,那么Django可能会认为它已经完成了迁移并且不会重做它。

确保找到上述两个文件之一并将其删除,然后运行上述脚本(以及您登录的createsuperuser)。