I was converting my existing app to api based. The structure of my file is as follow:
models.py
class BookDetail(models.Model):
title= models.CharField(max_length=10, default='title')
author= models.CharField(max_length=10)
series= models.CharField(max_length=10)
edition= models.CharField(max_length=10)
description= models.CharField(max_length=10)
keywords= models.CharField(max_length=10)
reading_age= models.CharField(max_length=10)
genre= models.CharField(max_length=10)
publishing_rights= models.CharField(max_length=10)
def __str__(self):
return self.title
class Addon(models.Model):
header= models.CharField(max_length=10)
footer= models.CharField(max_length=10, default='1')
additional_features = models.ForeignKey(BookDetail, related_name='additional_features',
on_delete=models.CASCADE, null=True)
def __str__(self):
return self.header
views.py
class BookDetailsList(APIView):
def get(self, request):
stocks = BookDetail.objects.all()
serializers = BookDetailsSerializer(stocks, many=True)
return Response(serializers.data)
def post(self, request):
serializer = BookDetailsSerializer(data=request.data)
print(serializer.is_valid())
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.py
class AddonSerializer(serializers.ModelSerializer):
class Meta:
model = Addon
fields = ('header', 'footer')
class BookDetailsSerializer(serializers.ModelSerializer):
additional_features = AddonSerializer(many=True)
class Meta:
model = BookDetail
fields = ('title', 'author','series', 'edition',
'description', 'keywords', 'reading_age',
'genre', 'publishing_rights','additional_features')
# fields = '__all__'
def create(self, validated_data):
additional_feature = validated_data.pop('additional_features')
book_detail = BookDetail.objects.create(**validated_data)
for a in additional_feature:
Addon.objects.create(additional_features=book_detail, **a)
# Addon.objects.create(additional_features=book_detail, **additional_feature)
return book_detail
My input data is in JSON format
{
"title": "lolwa",
"author": "asd",
"series": "string",
"edition": "a",
"description": "as",
"keywords": "sd",
"reading_age": "aasd",
"genre": "adasda",
"publishing_rights": "aadasd",
"additional_features": [{"header":"head",
"footer":"foot"}]
}
This is working fine. But what I really want is not passing my additional_features as a list which I'm currently doing, I want to pass it like this.
"additional_features": {"header":"head",
"footer":"foot"}
But my code throws error when I'm trying to pass it like this. I made the following changes in my serializer.py
class BookDetailsSerializer(serializers.ModelSerializer):
additional_features = AddonSerializer(many=False)
# additional_features = AddonSerializer(many=True)
class Meta:
model = BookDetail
fields = ('title', 'author','series', 'edition',
'description', 'keywords', 'reading_age',
'genre', 'publishing_rights','additional_features')
# fields = '__all__'
def create(self, validated_data):
additional_feature = validated_data.pop('additional_features')
book_detail = BookDetail.objects.create(**validated_data)
# for a in additional_feature:
# Addon.objects.create(additional_features=book_detail, **a)
Addon.objects.create(additional_features=book_detail, **additional_feature)
return book_detail
Made many=False and removed the for loop . Since both of them, **a and **additional_feature are
OrderedDict([('header', 'head'), ('footer', 'foot')])
I don't see a reason why it is failing.
This is the stack trace of the error
Internal Server Error: /bookdetails/
Traceback (most recent call last):
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 444, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 103, in get_attribute
instance = getattr(instance, attr)
AttributeError: 'RelatedManager' object has no attribute 'header'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/argo/Django/pagination-backend/backend/publishbook/views.py", line 21, in post
return Response(serializer.data, status=status.HTTP_201_CREATED)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 531, in data
ret = super(Serializer, self).data
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 500, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 487, in to_representation
attribute = field.get_attribute(instance)
File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 463, in get_attribute
raise type(exc)(msg)
AttributeError: Got AttributeError when attempting to get a value for field `header` on serializer `AddonSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `RelatedManager` instance.
Original exception text was: 'RelatedManager' object has no attribute 'header'.
From the structure of your models, a BookDetail object can have more than one Addon instances, since, Addon model have a foreign key to BookDetail.
If you want to have more than one Addons for a particular BookDetail, you cant update the Addon instance without using a list.
But, if its not the case, then I would recommend using a OneToOne relation instead of Foreign Key. Actually, its pretty ugly using a OneToOne field, rather you can just add the fields into your parent model(BookDetail), which can be defaulted to null, if there is None.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.