TypeError:" ModelBase不可迭代"

时间:2017-03-27 20:33:11

标签: python django python-3.x django-models django-rest-framework

在将我学到的技能应用到更大的企业项目之前,我正在开发一个小项目来练习Django REST Framework(以及后来的React前端)。

该项目是一个后端API,可以让某人看到主角在费城永远阳光的每一集中犯下的潜在罪行和侵权行为。为此,我创建了this GitHub存储库并在其中放置了一个Django项目。

我发现自己在浏览器调试视图中遇到错误,我在为网站添加新的模型/序列化/视图时无法弄清楚:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/characters/

Django Version: 1.10.6
Python Version: 3.6.0
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'offense_api.apps.OffenseApiConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  42.             response = get_response(request)

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/Users/person/Workspace/IASIP_API/offense_api/views.py" in character_list
  70.         return JsonResponse(serializer.data, safe=False)

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/rest_framework/serializers.py" in data
  729.         ret = super(ListSerializer, self).data

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/rest_framework/serializers.py" in data
  262.                 self._data = self.to_representation(self.instance)

File "/Users/person/.virtualenvs/IASIP/lib/python3.6/site-packages/rest_framework/serializers.py" in to_representation
  647.             self.child.to_representation(item) for item in iterable

Exception Type: TypeError at /characters/
Exception Value: 'ModelBase' object is not iterable

这只发生在“字符”页面上,该页面应与我的其他列表视图相同,即季节列表。

Serializers.py

from rest_framework import serializers
from offense_api.models import Season, Episode, Character


class SeasonSerializer(serializers.ModelSerializer):
    episodes = serializers.StringRelatedField(many=True)

    class Meta:
        model = Season
        fields = ('season_number', 'episodes')


class EpisodeSerializer(serializers.ModelSerializer):

    class Meta:
        model = Episode
        fields = ('episode_number', 'episode_title', 'episode_season')


class CharacterSerializer(serializers.ModelSerializer):

    class Meta:
        model = Character
        fields = ('character_legal_first_name', 'character_legal_last_name', 'character_preferred_name',)

Models.py

from django.db import models


class Season(models.Model):
    season_created = models.DateTimeField(auto_now_add=True)
    season_number = models.IntegerField(unique=True)

    def __unicode__(self):
        return self.season_number

    def __str__(self):
        return str(self.season_number)


class Episode(models.Model):
    episode_season = models.ForeignKey(Season, related_name='episodes', on_delete=models.CASCADE)
    episode_created = models.DateTimeField(auto_now_add=True)
    episode_number = models.IntegerField()
    episode_title = models.CharField(max_length=300, default='')

    def __unicode__(self):
        return '%d. %d' % (self.episode_season.season_number, self.episode_number)

    def __str__(self):
        return '%d. %d' % (self.episode_season.season_number, self.episode_number)

    class Meta:
        unique_together = ('episode_season', 'episode_number')
        ordering = ('episode_number',)


class Character(models.Model):
    character_created = models.DateTimeField(auto_now_add=True)
    character_legal_first_name = models.CharField(max_length=50, default='', null=True)
    character_legal_last_name = models.CharField(max_length=100, default='', null=True)
    character_preferred_name = models.CharField(max_length=150, default='', primary_key=True)

    def __unicode__(self):
        return self.character_preferred_name

    def __str__(self):
        return self.character_preferred_name

    class Meta:
        ordering = ('character_preferred_name',)

Views.py

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from offense_api.models import Episode, Season, Character
from offense_api.serializers import EpisodeSerializer, SeasonSerializer, CharacterSerializer


@csrf_exempt
def season_list(request):
    """
    List all seasons, or create a new one.
    :param request: 
    :return: 
    """
    if request.method == 'GET':
        seasons = Season.objects.all()
        serializer = SeasonSerializer(seasons, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SeasonSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)


@csrf_exempt
def season_detail(request, pk):
    """
    Retrieve, update, or delete a season.
    :param request: 
    :param pk: 
    :return: 
    """
    try:
        season = Season.objects.get(pk=pk)
    except Season.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = SeasonSerializer(season)
        return JsonResponse(serializer.data)

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = SeasonSerializer(season, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        season.delete()
        return HttpResponse(status=204)


@csrf_exempt
def character_list(request):
    """
        List all characters, or create a new one.
        :param request: 
        :return: 
        """
    if request.method == 'GET':
        characters = Character.objects.all()
        serializer = CharacterSerializer(Character, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = CharacterSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)

Urls.py

from django.conf.urls import url
from offense_api import views

urlpatterns = [
    url(r'^seasons/$', views.season_list),
    url(r'^seasons/(?P<pk>[0-9]+)/$', views.season_detail),
    url(r'^characters/$', views.character_list),
]

需要修改哪些内容才能解决此错误?

1 个答案:

答案 0 :(得分:2)

在views.py中,您将类Character传递给序列化程序。您应该传递数据字符。

也不要使用首选名称作为主键,它可能很容易变得非唯一