random
random

Reputation: 316

Django TypeError - 'ModelBase' object is not iterable

I have searched all the other threads with similar Questions on this topic but nothing is working. Hoping someone here can help. It only fails when trying to access 'api/orders'.

I am having the following errors

Traceback (most recent call last):
  File "C:\Users\projects\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\projects\venv\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\thard\projects\foreside\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\viewsets.py", line 114, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\views.py", line 476, in raise_uncaught_exception
    raise exc
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\mixins.py", line 46, in list
    return Response(serializer.data)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\serializers.py", line 760, in data
    ret = super().data
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\serializers.py", line 260, in data
    self._data = self.to_representation(self.instance)
  File "C:\Users\projects\venv\lib\site-packages\rest_framework\serializers.py", line 677, in to_representation
    return [

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

Here are the pertinent files

users.models.py

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    ADMIN = 1
    APPROVER = 2
    TRADER = 3
    USER_ROLE_CHOICES = (
        (ADMIN, 'admin'),
        (APPROVER, 'approver'),
        (TRADER, 'trader'),
    )
    role = models.PositiveSmallIntegerField(choices=USER_ROLE_CHOICES)
    REQUIRED_FIELDS = ['role', 'email']
    class Meta:
        verbose_name = 'user'
        verbose_name_plural = 'users'
    def get_full_name(self):
        return '%s %s' % (self.first_name, self.last_name)
    def get_short_name(self):
        return self.first_name
    def __str__(self):
        return self.username

class Order(models.Model):
    ADMIN = 1
    APPROVER = 2
    TRADER = 3
    USER_ROLE_CHOICES = (
        (ADMIN, 'admin'),
        (APPROVER, 'approver'),
        (TRADER, 'trader'),
    )
    name = models.CharField(max_length=50) 
    order_time = models.DateField(auto_now_add=True) 
    client = models.CharField(max_length=50)
    stock = models.CharField(max_length=10)
    qty = models.PositiveIntegerField()
    transaction_price = models.FloatField()
    payment_method = models.FloatField
    settlement = models.DateField(auto_now=True)
    status = models.CharField(max_length=50, default="new")
    reason = models.CharField(max_length=50, default="new order")
    modified_by = models.PositiveSmallIntegerField(choices=USER_ROLE_CHOICES)
    REQUIRED_FIELDS = [
        'order_time', 'stock', 'qty', 'transaction_price',
        'settlement', 'status', 'reason', 'modified_by',
        ]
    class Meta:
        verbose_name = 'order'
        verbose_name_plural = 'orders'

user.urls.py

from rest_framework.routers import DefaultRouter
from django.urls import path, include

from user import views

router = DefaultRouter()
router.register('users', views.UserViewSet, basename='user-list')
router.register('login', views.LoginView, basename='login')
router.register('orders', views.OrderViewSet, basename='order-list')

urlpatterns = [
    path('', include(router.urls)),
    path('account/logout/', views.LogoutView.as_view(), name='logout')
]

project.urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('user.urls'))
]

user.permissions.py

# from django.contrib.auth.models import Group
from rest_framework import permissions


ADMIN = 1
APPROVER = 2
TRADER = 3

def _is_in_role(user, role_name):
    try:
        return user.role == role_name
    except:
        return None

def _has_role_permission(user, required_roles):
    return any([_is_in_role(user, role_name) for role_name in required_roles])

class IsAdminUser(permissions.BasePermission):
    required_roles = [ADMIN,]

    def has_permission(self, request, view):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

    def has_object_permission(self, request, view, obj):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

class IsAdminOrApproverUser(permissions.BasePermission):
    required_roles = [ADMIN, APPROVER,]

    def has_permission(self, request, view):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

    def has_object_permission(self, request, view, obj):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

class IsAdminOrTraderUser(permissions.BasePermission):
    required_roles = [ADMIN, TRADER,]

    def has_permission(self, request, view):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

    def has_object_permission(self, request, view, obj):
        has_role_permission = _has_role_permission(request.user, self.required_roles)
        return request.user and has_role_permission

users.serializers.py

from rest_framework.serializers import ModelSerializer
from user.models import User, Order


class UserSerializer(ModelSerializer):
    class Meta:
        fields = ('id', 'first_name', 'last_name', 'username', 'password', 'role', 'email')
        model = User
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User.objects.create(**validated_data)
        user.set_password(validated_data['password'])
        user.is_staff = True
        user.save()

        return user

class OrderSerializer(ModelSerializer):
    class Meta:
        fields = (
            'id', 'name', 'order_time', 'client', 
            'stock', 'qty', 'transaction_price', 'payment_method', 'settlement',
            'status', 'reason', 'modified_by',
            )
        model = Order

pertinent parts of settings.py

...
INSTALLED_APPS = [
    ...,

    'rest_framework',
    'rest_framework.authtoken',
    'user',
]

AUTH_USER_MODEL = 'user.User'
...

user.views.py

from django.shortcuts import render

from rest_framework import status
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet, ModelViewSet
from rest_framework.permissions import AllowAny
from user.permissions import IsAdminUser, IsAdminOrApproverUser, IsAdminOrTraderUser
from user.models import User, Order
from user.serializers import UserSerializer, OrderSerializer


class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = [TokenAuthentication]

    def get_permissions(self):
        permission_classes = []
        if self.action == 'create':
            permission_classes = [IsAdminUser]
        elif self.action == 'list':
            permission_classes = [IsAdminUser]
        elif self.action == 'retrieve' or self.action == 'update' or self.action == 'partial_update':
            permission_classes = [IsAdminUser]
        elif self.action == 'destroy':
            permission_classes = [IsAdminUser]
        return [permission() for permission in permission_classes]


class LoginView(ViewSet):
    serializer_class = AuthTokenSerializer

    def create(self, request):
        return ObtainAuthToken().post(request)


class LogoutView(APIView):
    def get(self, request, format=None):
        request.user.auth_token.delete()
        return Response(status=status.HTTP_200_OK)

class OrderViewSet(ModelViewSet):
    queryset = Order
    serializer_class = OrderSerializer
    authentication_classes = [TokenAuthentication]
    
    def get_permissions(self):
        permission_classes = []
        if self.action == 'create':
            permission_classes = [IsAdminOrTraderUser]
        elif self.action == 'list':
            permission_classes = [IsAdminOrTraderUser]
        elif self.action == 'retrieve' or self.action == 'update':
            permission_classes = [IsAdminOrTraderUser]
        elif self.action == 'partial_update':
            permission_classes = [IsAdminOrApproverUser]
        elif self.action == 'destroy':
            permission_classes = [IsAdminUser]
        return [permission() for permission in permission_classes]

. .

Upvotes: 0

Views: 8868

Answers (2)

Manoj Parmar
Manoj Parmar

Reputation: 79

You don't define a direct model name to the queryset it will raise an error

queryset = Order //(it is a wrong way),

The right way is to define query set

queryset = Order.objects.all()

Upvotes: 1

JPG
JPG

Reputation: 88509

The queryset attribute must be a QuerySet rather than a model class

class OrderViewSet(ModelViewSet):
    queryset = Order.objects.all()
    # rest of your code

Upvotes: 5

Related Questions