Django 'ModelBase' objeto no es iterable TipoError

Consiguiendo lo siguiente de una prueba de unidad en Django. No puedo imaginar la razón por la que esto está pasando.

Mis migraciones parecen idénticas a las otras migraciones que he hecho.

Además, fui capaz de ejecutar esto en mi máquina local en la sección de administración, así que mi otra pregunta es esta gran cosa si está sucediendo durante la prueba si puede ser empujado en vivo. Intentando seguir las mejores prácticas aquí, así que aprecia las opiniones de otros sobre eso.

modelos. py

class LeadComplete(models.Model):
    """Complete lead info"""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.DO_NOTHING,
    )
    title=models.CharField(max_length=255)
    time_minutes = models.IntegerField()
    score = models.DecimalField(max_digits=5, decimal_places=2)
    link = models.CharField(max_length=255, blank=True)
    client = models.ManyToManyField('Client')
    
    def __str__(self):
        return self.title

serializadores.py

class LeadCompleteSerializer(serializers.ModelSerializer):
    """Serialize a leadComplete"""
    client = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Client.objects.all()
    )
    
    class Meta:
        model = LeadComplete
        fields = [
            'id', 'title', 'time_minutes', 'score', 'link', 'client',
        ]
        read_only_fields = ('id',)

vistas. py

class LeadCompleteViewSet(viewsets.ModelViewSet):
    """Manage LeadComplete in the database"""
    serializer_class = serializers.LeadCompleteSerializer
    queryset = LeadComplete.objects.all()
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        """Retrieve the leadcomplete for the authed user"""
        return self.queryset.filter(user=self.request.user)

test_lead_complete_api.py

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse

from rest_framework import status 
from rest_framework.test import APIClient

from core. models import LeadComplete

from leads.serializers import LeadCompleteSerializer

LEADCOMPLETE_URL = reverse('leads:leadcomplete-list')

def sample_leadComplete(user, **params):
    """Create and return a sample leadComplete"""
    defaults = {
        'title': 'Samle Company',
        'time_minutes': 10,
        'score': 5.00,
    }
    defaults.update(params)

    return LeadComplete.objects.create(user=user, **defaults)

def PublicLeadCompleteApiTests(TestCase):
    """Test unauthenticated LeacComplete access"""

    def setUp(self):
        self.client = APIClient()

    def test_auth_required(self):
        """"Test that authentication is required"""
        res = selft.client.get(LEADCOMPLETE_URL)

        self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED)
    
class PrivateLeadCompleteApiTests(TestCase):
    """"Test authenticated recipe API access"""

    def setUp(self):
        self.client = APIClient()
        self.user = get_user_model().objects.create_user(
            '[email protected]',
            'testpass'
        )
        self.client.force_authenticate(self.user)

    def test_retrieve_leadComplete(self):
        """Test retrieving LeadComplete list"""
        sample_leadComplete(user=self.user)
        sample_leadComplete(user=self.user)

        res = self.client.get(LEADCOMPLETE_URL)

        leadComplete = LeadComplete.objects.all().order_by('-id')
        serializer = LeadCompleteSerializer(LeadComplete, many=True)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data, serializer.data)

    def test_leadComplete_limited_to_user(self):
        """Test retrieving leadComplete for user"""
        user2 = get_user_model().objects.create_user(
            '[email protected]',
            'password123'
        )
        sample_leadComplete(user=user2)
        sample_leadComplete(user=self.user)

        res = self.client.get(LEADCOMPLETE_URL)

        leadComplete = LeadComplete.objects.filter(user=self.user)
        serializer = LeadCompleteSerializer(leadComplete, many=True)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data, serializer.data)

error:

ERROR: test_retrieve_leadComplete (leads.tests.test_leadcomplete_api.PrivateLeadCompleteApiTests)
Test retrieving LeadComplete list
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/app/leads/tests/test_leadcomplete_api.py", line 58, in test_retrieve_leadComplete
    self.assertEqual(res.data, serializer.data)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 768, in data
    ret = super(ListSerializer, self).data
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 262, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 686, in to_representation
    self.child.to_representation(item) for item in iterable
TypeError: 'ModelBase' object is not iterable

Pregunta hecha hace 3 años, 4 meses, 29 días - Por cyberjedi


3 Respuestas:

  • El cliente de prueba devuelve datos en la propiedad de contenido.

    Prueba. res.content en lugar de res.data

    def test_retrieve_leadComplete(self):
        """Test retrieving LeadComplete list"""
        sample_leadComplete(user=self.user)
        sample_leadComplete(user=self.user)
    
        res = self.client.get(LEADCOMPLETE_URL)
    
        leadComplete = LeadComplete.objects.all().order_by('-id')
        serializer = LeadCompleteSerializer(LeadComplete, many=True)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.content, serializer.data)
    

    Respondida el Dec 18, 2020 a las 03:14 - por byteninja8245

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás viendo, 'ModelBase' object is not iterable, indica que estás pasando incorrectamente el modelo LeadComplete en tu serializer en el archivo test_lead_complete_api.py.

    En la función test_retrieve_leadComplete, estás pasando LeadCompleteSerializer(LeadComplete, many=True) en lugar de LeadCompleteSerializer(leadComplete, many=True). Esto significa que estás intentando serializar la clase LeadComplete en lugar de una instancia o queryset de LeadComplete.

    Para corregir este error, asegúrate de pasar la variable leadComplete (que es la queryset que obtuviste filtrando los LeadComplete por el usuario) al serializer en vez del modelo en sí. Debes modificar la línea en cuestión de la siguiente manera:

    
    serializer = LeadCompleteSerializer(leadComplete, many=True)
    

    Al hacer esta corrección, la queryset leadComplete se pasará correctamente al serializer LeadCompleteSerializer para serializar los datos y el error 'ModelBase' object is not iterable debería desaparecer.

    Respondida el Dec 19, 2020 a las 03:19 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error TipoError: 'ModelBase' objeto no es iterable en tu prueba de unidad de Django ocurre porque estás intentando iterar sobre un objeto ModelBase en lugar de un conjunto de instancias de modelo.

    En tu prueba, en la línea 58, estás intentando comparar res.data con serializer.data, donde serializer.data es una lista de representaciones serializadas de instancias de LeadComplete, mientras que res.data es un objeto ModelBase que representa el conjunto de consultas para el modelo LeadComplete.

    Para resolver este problema, necesitas actualizar tu prueba para iterar sobre las instancias de LeadComplete en el conjunto de consultas y compararlas con las representaciones serializadas individuales en serializer.data. Aquí tienes una versión actualizada de la prueba:

    python
    def test_retrieve_leadComplete(self):
        """Test retrieving LeadComplete list"""
        sample_leadComplete(user=self.user)
        sample_leadComplete(user=self.user)
    
        res = self.client.get(LEADCOMPLETE_URL)
    
        leadComplete = LeadComplete.objects.filter(user=self.user).order_by('-id')
        serializer = LeadCompleteSerializer(leadComplete, many=True)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data, serializer.data)
    

    Al iterar sobre las instancias de LeadComplete en el conjunto de consultas y compararlas con las representaciones serializadas individuales, puedes verificar que los datos devueltos por la API sean correctos.

    Respondida el Dec 19, 2020 a las 03:28 - por Gemini

    Votos positivos: 0 | Votos negativos: 0