2016-04-09 2 views
0

Прежде чем я получу очевидный ответ, о проверке базы данных, я начну с того, что я уже проверил this post, который имеет почти идентичная настройка для моего, и решения по удалению базы данных и миграции и добавление значения по умолчанию в таблицу не работало, как и ожидалось. Однако я ожидаю, что решение будет довольно простым.Учебник Django REST Framework, OperationalError: table snippets_snippet не имеет столбца с именем owner_id

Итак, я сказал the tutorial for django-rest-framework, и моя проблема началась с part 4. В учебнике говорится следующее:

Now if you open up the browser again and refresh the page you'll see a 'Login' link in the top right of the page. If you log in as one of the users you created earlier, you'll be able to create code snippets again.

Once you've created a few code snippets, navigate to the '/users/' endpoint, and notice that the representation includes a list of the snippet pks that are associated with each user, in each user's 'snippets' field.

Итак, я попытался создать «фрагменты» объекты с manage.py оболочки, как и в первой части урока, с помощью следующего кода:

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

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

И вот где это кончается. .save() вызывает ошибку, на которую я напечатал traceback, ниже.

Используя совет по ранее заданному вопросу, я немного изменил настройки, но до сих пор получаю ошибку. Вот установка:

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 
+0

Вы пытались запустить 'makemigrations' и' migrate'? – vmonteco

+0

@vmonteco - Да. Как было сказано ранее в моем вопросе, я сначала запускал миграции, без проблем, пока не ударил команду .save() в оболочке. Затем я удалил миграцию и базу данных, и я запустил их снова, только чтобы повторить ту же проблему. –

+0

Не могли бы вы попробовать «./manage.py makemigrations <имя вашего приложения>», а затем перенести? – vmonteco

ответ

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 
+0

Спасибо. Это решило проблему добавления owner_id в таблицу фрагментов, но, возможно, это создало еще одну проблему, которая заключается в том, что конечная точка, определенная в '/ snippets/urls.py', кажется, не работает, что может быть следствием изменение в модели: URL: 'url (r '^ users/$', UserList.as_view())', а также URL UserDetail возвращают 'AttributeError at/users/1/ 'Пользователь' объект не имеет атрибутов 'snippets'', что указывает на то, что сериализаторы не выполняют свою работу. Возможно, 'OnetoOneField (Пользователь)' является неправильным выбором. –

+1

О, мой плохой, я удалил связанное_имя = 'фрагменты' в смене модели. По умолчанию, если вы не даете связанное имя, django использует «somefieldname_set» для обратного связывания «somefieldname». Поэтому в UserSerializer измените «фрагменты» на «snippets_set», и он должен работать нормально. – Abhinav

+0

Подождите, всего лишь секунда - если я вернусь к 'related_name = 'snippets'', если это сработает или изменит поле модели, чтобы это не сработало? И, чтобы быть уверенным, вы могли бы обновить свой ответ? –

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 могут подумать, что уже сделал миграцию и не переделывать ,

Убедитесь, что вы нашли один из двух вышеупомянутых файлов и удалили их, а затем запустите указанный выше сценарий (плюс создатель createuperuser для входа в систему).

+0

Исходный путь, который я удалил, перетаскивал в корзину, а не в 'cmd', но я попробовал свой метод (без флага' -f', потому что я в Windows), и он все еще не работает. Такая же ошибка в 'snippet.save()' в оболочке manage.py. –

+0

, и вы также удалили содержимое каталога фрагментов/миграций? – Linovia

+0

Да. Я делал это несколько раз и продолжаю получать ту же ошибку. Либо что-то подозрительное с самой моделью, либо с помощью метода save(). Я запускаю python 3.5 и django 1.9. –

Смежные вопросы