Reputation: 3
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
Reputation: 661
You can access user by the order object
def get_user(self,obj):
serializer = UserSerializer(obj.user)
return serializer.data
Upvotes: 0
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