【问题标题】:TypeError: "ModelBase is not iterable"类型错误:“模型库不可迭代”
【发布时间】:2017-03-27 20:33:10
【问题描述】:

我正在做一个小项目来练习 Django REST 框架(以及后来的 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),
]

为了避免这个错误需要修改什么?

【问题讨论】:

  • 我看到您在 0004_auto_20170327_1633.py 迁移中删除了 Character 模型。这可能是你问题的根源。尽管您尚未提交 0006 迁移,但我可以在您的数据库的 django_migrations 表中看到跟踪。由于Character 似乎又回到了模型中,你能告诉我们那个迁移文件吗?
  • @RaphaëlGomès 我已根据您的要求上传了 0006_character.py。

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


【解决方案1】:

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

也不要使用首选名称作为主键,它很容易成为非唯一的

【讨论】:

    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 2021-10-28
    • 2012-10-30
    • 2016-03-10
    • 2017-03-05
    相关资源
    最近更新 更多