Marilyn Marquez
Marilyn Marquez

Reputation: 3

500 error Django Rest Frameworks Serializer

newbie here. I am following a React+Django tutorial (create a store) in which we are using Django RestFrameworks (and this is my first time using it). We are using serializers with JWT tokens for authentication. The problem I'm having is when I try to create a new "order" in the page, I get a 500 error:

Internal Server Error: /api/order/add Traceback (most recent call last): File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 103, in view return self.dispatch(request, *args, **kwargs) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch response = self.handle_exception(exc) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception raise exc File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/decorators.py", line 50, in handler return func(*args, **kwargs) File "/Volumes/Samsung_T5/GitHub/ecommerce/backend/base/views/order_views.py", line 59, in addOrderItems return Response(serializer.data) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 555, in data ret = super().data File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 253, in data self._data = self.to_representation(self.instance) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 522, in to_representation ret[field.field_name] = field.to_representation(attribute) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/fields.py", line 1886, in to_representation return method(value) File "/Volumes/Samsung_T5/GitHub/ecommerce/backend/base/serializers.py", line 74, in get_user return serializer.data File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 555, in data ret = super().data File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 253, in data self._data = self.to_representation(self.instance) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 522, in to_representation ret[field.field_name] = field.to_representation(attribute) File "/Volumes/Samsung_T5/GitHub/ecommerce/venv/lib/python3.9/site-packages/rest_framework/fields.py", line 1886, in to_representation return method(value) File "/Volumes/Samsung_T5/GitHub/ecommerce/backend/base/serializers.py", line 19, in get_name name = obj.first_name AttributeError: 'QuerySet' object has no attribute 'first_name' [17/Sep/2022 19:03:07] "POST /api/order/add HTTP/1.1" 500 147510

My serializers.py file is as follows:

from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import RefreshToken
from .models import Product, Order, OrderItem, ShippingAddress



class UserSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField(read_only = True)
    isAdmin = serializers.SerializerMethodField(read_only = True)
    class Meta:
        model = User
        fields= ['id', 'first_name','email', 'name', 'isAdmin']
    
    def get_isAdmin(self, obj):
        return obj.is_staff
    
    def get_name(self, obj):
          name = obj.first_name
          if name == '':
              name = obj.email
          return name 

class UserSerializerWithToken(UserSerializer):
    token = serializers.SerializerMethodField(read_only = True)
    class Meta:
        model=User
        fields = ['id', 'username', 'email', 'name', 'isAdmin', 'token']
        
    def get_token(self, obj):
        token = RefreshToken.for_user(obj)
        return str(token.access_token)
        

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields= '__all__'
        
class ShippingAddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = ShippingAddress
        fields= '__all__'
        
class OrderItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields= '__all__'

class OrderSerializer(serializers.ModelSerializer):
    orderItems = serializers.SerializerMethodField(read_only = True) #formerly orders
    shippingAddress = serializers.SerializerMethodField(read_only = True)
    user = serializers.SerializerMethodField(read_only = True)
    class Meta:
        model = Order
        fields= '__all__'
    
    def get_orderItems(self,obj): #former get_orders
        items = obj.orderitem_set.all()
        serializer = OrderItemSerializer(items, many = True)
        return serializer.data
    
    def get_shippingAddress(self,obj):
        try:
            address = ShippingAddressSerializer(obj.shippingAddress, many=False) #we can do it like this because this is  a 1:1 field
        except:
            address = False
            
        return address
    
    def get_user(self,obj):
        user =User.objects.all() #previously obj.user.all(), but that gave an error
        serializer = UserSerializer(user, many = False)
        return serializer.data

my user_views.py:

from django.shortcuts import render
from django.contrib.auth.hashers import make_password
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import status

from base.models import User
from base.serializers import  UserSerializer, UserSerializerWithToken


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        data = super().validate(attrs)
        serializer = UserSerializerWithToken(self.user).data
        for key, value in serializer.items():
            data[key]=value
        return data
 
class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer
    
    
@api_view(['POST'])    
def registerUser(request):
    data=request.data
    try:
        user=User.objects.create(
            first_name = data['first_name'],
            #last_name= data['last_name'], this was causing error: fields didn't match
            username = data['email'], 
            email = data['email'],
            password = make_password(data['password'])
    )
            
        serializer = UserSerializerWithToken(user, many=False)
        return Response(serializer.data)
    except:
        message={'detail':'User with this email already exists'}
        return Response(message, status=status.HTTP_400_BAD_REQUEST)
 

@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def updateUserProfile(request):
    user = request.user 
    serializer = UserSerializerWithToken(user, many=False)
    
    data =request.data 
    user.first_name=data['first_name']
    user.username=data['email']
    user.email=data['email']
    if data['password'] != ' ' :
        user.password =  make_password(data['password']) 
    
    user.save() 
    
    return Response(serializer.data)

    
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getUserProfile(request):
    user = request.user 
    serializer = UserSerializer(user, many=False)
    return Response(serializer.data)

@api_view(['GET'])
@permission_classes([IsAdminUser])
def getUsers(request):
    users = User.objects.all() 
    serializer = UserSerializer(users, many=True)
    return Response(serializer.data)

We are using Django's default User model for the tutorial.

Please, can someone tell me what I'm doing wrong? Thank you very much in advance

UPDATE: Someone asked to see the models, here they are:

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

# Create your models here.

class Product (models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) 
    name = models.CharField(max_length = 200, null=True, blank=True) 
    image = models.ImageField(null=True, blank=True)
    ingredients = models.CharField(max_length = 300, null=True, blank=True)
    category = models.CharField(max_length = 200, null=True, blank=True)
    description = models.TextField(max_length = 2000, null=True, blank=True)
    rating = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    numReviews = models.IntegerField(null=True, blank=True, default = 0)
    price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    countInStock = models.IntegerField(null=True, blank=True, default = 0)
    createdAt = models.DateTimeField(auto_now_add=True)
    id = models.AutoField(primary_key=True, editable=False)
    

class Review(models.Model):
    product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    name = models.CharField(max_length = 200, null=True, blank=True) 
    rating = models.IntegerField(null=True, blank=True, default = 0)
    comment = models.TextField(max_length = 2000, null=True, blank=True)
    id = models.AutoField(primary_key=True, editable=False)
    
    def __str__(self):
        return str(self.rating)
    
class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    paymentMethod = models.CharField(max_length = 200, null=True, blank=True)
    taxPrice = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    shippingPrice = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    totalPrice = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    is_Paid = models.BooleanField(default = False)
    paidAt = models.DateTimeField(auto_now_add=False, null=True, blank=True)
    isDelivered = models.BooleanField(default = False)
    deliveredAt = models.DateTimeField(auto_now_add=False, null=True, blank=True)
    createdAt = models.DateTimeField(auto_now_add=True)
    id = models.AutoField(primary_key=True, editable=False)
    
    def __str__(self):
        return str(self.createdAt)
    
class OrderItem(models.Model):
      product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
      order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
      name = models.CharField(max_length = 200, null=True, blank=True) 
      qty = models.IntegerField(null=True, blank=True, default = 0)
      price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
      image = models.CharField(max_length = 200, null=True, blank=True) 
      id = models.AutoField(primary_key=True, editable=False)
      
      def __str__(self):
            return str(self.name)
        
        
class ShippingAddress(models.Model):
    order = models.OneToOneField(Order, on_delete=models.CASCADE, null=True, blank=True)
    address = models.CharField(max_length=200, null=True, blank=True)
    city = models.CharField(max_length=200, null=True, blank=True)
    postalCode = models.CharField(max_length=200, null=True, blank=True)
    country = models.CharField(max_length=200, null=True, blank=True)
    shippingPrice = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
    id = models.AutoField(primary_key=True, editable=False)
    
    def __str__(self):
        return str(self.address)




  

Upvotes: 0

Views: 1014

Answers (2)

Krishna Singhal
Krishna Singhal

Reputation: 661

You can access user by the order object

 def get_user(self,obj):
    serializer = UserSerializer(obj.user)
    return serializer.data

Upvotes: 0

WoodyG
WoodyG

Reputation: 200

As the error suggests, you are trying to retrieve the first_name from a Queryset rather than from an individual instance/object.

This is because in the get_user method, you are passing a Queryset to the UserSerializer, rather than a User object.

I guess what you are trying to do is pass the user associated with the order to the UserSerializer. If this is the case, you can change the get_user method to the following:

def get_user(self,obj):
    serializer = UserSerializer(obj.user)
    return serializer.data

Upvotes: 0

Related Questions