Original exception text was: 'QuerySet' object has no attribute 'weight' - django-rest-framework

I got an Exception
Got AttributeError when attempting to get a value for field weight on serializer WeightHistorySerializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
Original exception text was: 'QuerySet' object has no attribute 'weight'.
When I tried to retrive data.
models.py
class WeightHistory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
weight = models.FloatField(null=False, blank=False)
created_at = models.DateTimeField(auto_now_add=True)
serializers.py
class WeightHistorySerializer(serializers. HyperlinkedModelSerializer):
class Meta:
model = WeightHistory
fields = (
'id',
'weight',
'user_id',
'created_at'
)
read_only_fields = ('id',)
views.py
def weight_history_detail(request, user_id):
# Retrieve, update or delete a weight_history/detail.
try:
weight_history = WeightHistory.objects.filter(user_id=user_id)
except WeightHistory.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = WeightHistorySerializer(weight_history)
return Response(serializer.data)
If it change to
weight_history = WeightHistory.objects.get(user_id=user_id)
It returns only one row, But I want all the rows with given user_id. So, What should I do to get all list with given user_id.

'QuerySet' object has no attribute 'weight'.
Yes. QuerySet is a Set, a list of objects.
<QuerySet [<Object1>, <Object2>,..]>
And that list has no attribute weight. Instead, the objects inside the QuerySet has the attribute weight.
weight_history = WeightHistory.objects.filter(user_id=user_id)
filter returns a QuerySet, a list of WeightHistory objects with user_id=user_id.
And you are trying to serialize the list as a single object.
Instead of this:
serializer = WeightHistorySerializer(weight_history)
Do this:
serializer = WeightHistorySerializer(weight_history, many=True)
many=True tells the serializer that a list of objects being passed for serialization.
Moreover,
try:
weight_history = WeightHistory.objects.filter(user_id=user_id)
except WeightHistory.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
This doesn't throw an exception at all. filter returns an empty QuerySet if no objects exist. <QuerySet []>.
So the final code is:
def weight_history_detail(request, user_id):
# Retrieve, update or delete a weight_history/detail.
weight_history = WeightHistory.objects.filter(user_id=user_id)
if weight_history.count()<1:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = WeightHistorySerializer(weight_history, many=True)
return Response(serializer.data)

views.py
def weight_history_detail(request, user_id):
# Retrieve, update or delete a weight_history/detail.
try:
weight_history = WeightHistory.objects.get(user_id=user_id) #get
except WeightHistory.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = WeightHistorySerializer(weight_history)
return Response(serializer.data)
use get instead of filter it will solve you error

Related

I have to create serializer instance without data since i am not accepting any data from user

Here i am trying to create serializer instance without data argument because all i want to create a "Like" object which requires "user" object which i can get from request and "post" object that i am getting through querying Post model with pk but since i am not passing any data argument while deserializing it will throw an error.
So how can create instance without passing data argument or do i have to change my code and add data argument?
class Like(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="likes")
liked_by = models.ForeignKey(User, on_delete=models.RESTRICT, related_name = "liked_posts")
def __str__(self):
return "{0} liked by {1}".format(self.post.img, self.liked_by.username)
class LikeSerializer(serializers.ModelSerializer):
liked_by = UserSerializer(read_only=True)
class Meta:
model = Like
fields = ("id","post", "liked_by")
class AddLike(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk):
post = Post.objects.get(pk=pk)
user = request.user
serializer = LikeSerializer()
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.save(post=post, liked_by=user)
return Response(data= serializer.data, status=status.HTTP_201_CREATED)
I think you can set the post field as read_only in the LikeSerializer.
class LikeSerializer(serializers.ModelSerializer):
liked_by = UserSerializer(read_only=True)
class Meta:
model = Like
fields = ("id","post", "liked_by")
extra_kwargs = {
'post': { 'read_only': True }
}

How to serialize multiple query set to json Response in django rest frame work

I am getting a list of committees by user using a get method in which I am sending a user id but I am getting an error Committee object is not serialize I have serializer created but I dont't know how to serializer the queryset of that particular user id result.
below is my views.py file
def get(self, request, user_id):
get_committees = Committee.objects.filter(user=Profile.objects.get(id=user_id))
data = {
"status": "success",
"data":get_committees
}
res = Response(serializer.data, status=status.HTTP_200_OK)
below is my serializer.py
class MyCommitteesSerializer(serializers.ModelSerializer):
def get_queryset(self, user_id):
my_committees =
Committee.objects.filter(user=Profile.objects.get(id=user_id))
return my_committees
from your code in get method
"data":get_committees
this get_committees is a list and you are trying to return a list but you can only return json, and so you are getting the message.
You can do this in a better way
define your serializer as -
class MyCommitteesSerializer(serializers.ModelSerializer):
class Meta:
model = Committee
fields = ""_all__"
and define your views as -
class MyCommitteesView(generics.ListAPIView):
serializer_class = MyCommitteesSerializer
def get_queryset(self):
queryset = Committee.objects.filter(user=Profile.objects.get(id=self.request.user_id))
return queryset
the serializer will take care of serialization and you can customize this according to your needs.
or else you will have to manually convert your get_committes into json format before returning.

'QuerySet' object has no attribute 'pk'

#models
class Student(models.Model):
firstname = models.CharField(max_length=100,default='ll')
lastname = models.CharField(max_length=100,default='fewf')
id_code = models.CharField(max_length=10,default=0,unique=True)
melli = models.CharField(max_length=30,default=0,unique=True)
personal_pic = models.ImageField(upload_to=studentFile)
major = models.ForeignKey(Major, on_delete=models.PROTECT,default=0)
date_of_start = models.DateField(default=datetime.date.today)
def __str__(self):
return self.id_code
#views
class loginView(APIView):
def post(self, request):
data = request.data
melli = data.get('melli')
id_code = data.get('id_code')
student = Student.objects.filter(id_code=id_code,melli=melli)
if not student.exists():
return Response('error')
serializer = StudentSerializer(student,data=data)
serializer.is_valid()
return Response(serializer.data)
when i try to submit a post request i was excepted to recive a response but i got an error. how can i solve it?
You serialize a collection of elements, so you should work with many=True:
serializer = StudentSerializer(student,data=data, many=True)
in case you want to only work with a single object, you need to retrieve a single object, not a collection of objects, for example with .get(…) [Django-doc] instead of .filter(…) [Django-doc].
Model.filter returns a queryset, which is like a list of models, rather than a specific model. Instead, you should use get, which returns a single model instance:
student = Student.objects.get(id_code=id_code,melli=melli)
If you intend on there being more than 1 student in this specific query, you can add many=True to your serializer instead:
serializer = StudentSerializer(student,data=data, many=True)

Cannot generate post request for multiple data

I am trying to take input multiple data object in post request, but getting such error.
non_field_errors: [ Invalid data. Expected a dictionary, but got a list. ]
models.py
class OrderProduct(BaseModel):
product = models.ForeignKey(Product,on_delete=models.CASCADE)
order = models.ForeignKey(Order,on_delete=models.CASCADE)
order_product_price = models.FloatField(blank=False,null=False,default=0) # product may belong to offer do the price
order_product_qty = models.FloatField(default=1)
serializers.py
class OrderProductSerializer(serializers.ModelSerializer):
def update(self,instance,validated_data):
product = self.validated_data.pop('product')
order = self.validated_data.pop('order')
instance.orderproduct_qty =
self.validated_data.get('orderproduct_qty',instance.orderproduct_qty)
instance.product = product
instance.order = order
instance.save()
return instance
class Meta:
model = OrderProduct
fields = '__all__'
views.py
def post(self,request,*args,**kwargs):
if request.data['contact_number'] == '':
request.POST._mutable =True
request.data['contact_number'] = request.user.mobile_number
request.POST._mutable = False
serializer = OrderSerializer(data=request.data,many=isinstance(request.data,list),context={'request': request})
print(serializer)
if serializer.is_valid():
serializer.save(user = request.user,created_by = request.user)
return Response(serializer.data,status=status.HTTP_200_OK)
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
urls.py
path('orderproduct/',views.OrderProductList.as_view()),
When you call serializer.save(). It's only perform create() action which is only create one and accept dictionary data type only. If you want to save multiple data like that, you will have to override the create function of the serializer class. You can do something similar like this or run a for loop.
serializers.py
def create(self, validate_data):
# Get the data objects you need to perform bulk create
order_products = OrderProduct.objects.bulk_create(validate_data)
return order_products
views.py
if serializer.is_valid(raise_exception=True):
# Replace the serializer.save() by this line to trigger the create method in serializer
self.perform_create(serializer)
return Response(...)

Getting "AttributeError: 'QuerySet' object has no attribute '_meta'" on django rest "PUT" method

I am trying to update the record with PUT method, Getting AttributeError: 'QuerySet' object has no attribute '_meta'.
My models.py:
class TableInfo(models.Model):
table_name = models.CharField(max_length=10)
columns = JSONField(null=False)
serializer.py:
class TableInfoSerializer(serializers.ModelSerializer):
class Meta:
model = TableInfo
fields = '__all__'
views.py :
#api_view(['GET','PUT'])
def table_info(request):
try:
queryset = TableInfo.objects.all()
print("1")
except TableInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
print("2")
serializer_class = TableInfoSerializer(queryset, many=True)
return Response(serializer_class.data)
elif request.method == 'PUT':
print(request.data)
serializer = TableInfoSerializer(queryset, data=request.data)
if serializer.is_valid():
serializer.save()
print("4")
return HttpResponse(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
code is breaking at if serializer.is_valid():
On "GET" I am getting the result. Please help me with "PUT" method.
This error happens with PUT because the serializer tries to access the Meta class on the model instance it is updating, but fails because you are not passing a model instance - you're passing a queryset as indicated in the comments.
So you need to pass an instance, and to specify which instance you would normally pass the instance id via the URL. For that you would be best to separate out your views, and create a table_detail view for retrieving and updating a specific instance.
#api_view(['GET','PUT'])
def table_detail(request, pk):
try:
table_info = TableInfo.objects.get(pk=pk) # Lookup a specific object
except TableInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer_class = TableInfoSerializer(table_info)
return Response(serializer_class.data)
elif request.method == 'PUT':
serializer = TableInfoSerializer(table_info, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Your table_info view can then just handle the list operation.
#api_view(['GET'])
def table_info(request):
if request.method == 'GET':
queryset = TableInfo.objects.all()
serializer_class = TableInfoSerializer(queryset, many=True)
return Response(serializer_class.data)

Resources