Apply foreign key (Brand) into the User Brand object - python

I am having an issue with the following line: user_brand = UserBrand(user=user, brand=serializers), I keep getting the following error:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/jeansymolanza/projects/adsoma-api/api/views.py", line 137, in post
return self.create(request, *args, **kwargs)
File "/Users/jeansymolanza/projects/adsoma-api/api/views.py", line 154, in create
user_brand = UserBrand(user=user, brand=serializers)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py", line 439, in __init__
setattr(self, field.name, rel_obj)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 207, in __set__
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "<module 'rest_framework.serializers' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/serializers.py'>": "UserBrand.brand" must be a "Brand" instance.
All I want to do is apply the foreign key (Brand) into the User Brand object.
views.py
class BrandSignup(generics.CreateAPIView):
"""
Brand signup
HTTP POST
"""
queryset = Brand.objects.all()
serializer_class = BrandSignupSerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
if User.objects.filter(email=request.data['email']).exists():
response_details = {
'data': "",
'message': "This email account is already in use. Please try using another one.",
'code': "400",
'status': HTTP_400_BAD_REQUEST
}
return Response(response_details, status=response_details['status'])
else:
serializer = self.get_serializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
user = User(email=request.data['email'], password=request.data['password'],
account_type=request.data['account_type'])
user.save()
user_brand = UserBrand(user=user, brand=serializer)
user_brand.save()
response_details = {
'data': request.data,
'message': "Account created successfully.",
'code': "201",
'status': HTTP_201_CREATED
}
else:
response_details = {
'data': serializer.errors,
'message': "Your account cannot be created at this moment in time. Please try again later.",
'code': "400",
'status': HTTP_400_BAD_REQUEST
}
return Response(response_details, status=response_details['status'])
models.py
class Brand(models.Model):
"""
Brand model
"""
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=255, null=True, default=None)
brand = models.CharField(max_length=255, null=True, default=None)
phone = models.CharField(max_length=255, null=True, default=None)
website = models.CharField(max_length=255, null=True, default=None)
class Meta:
verbose_name_plural = "Brands"
def __str__(self):
return "%s" % self.brand
class UserBrand(models.Model):
"""
User brand model
"""
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
user = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
brand = models.ForeignKey(Brand, null=False, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "User Brands"
def __str__(self):
return "%s - %s" % (self.user, self.brand)

You're trying to pass a BrandSignupSerializer object to the UserBrand constructor as the brand... You need a Brand object instead. You should be able to fix this by replacing your line with
user_brand = UserBrand(user=user, brand=serializer.instance)

Related

Django saving ManyToManyField gives error: Field 'id' expected a number but got 'str'

I'm trying to use a ManyToManyField to create a model attribute with a set of options (instances of the m2m model). When I go to save the model in my ModelForm, save_m2m() gives an error saying that Field 'id' expected a number but got 'U'.
Here is my code:
Models:
class Choices(models.Model):
description = models.CharField(max_length=100)
class Listing(models.Model):
idtag = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
published = models.DateTimeField("Date Published", default=timezone.now)
description = models.TextField()
price = models.PositiveBigIntegerField()
currency = models.ManyToManyField(Choices)
location = models.CharField(max_length=100)
only_location = models.BooleanField(default=False)
tags = TaggableManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('main:listingdetails', kwargs={'pk': self.pk})
View:
#login_required
def createview(request):
if request.method == "POST":
creationform = ListingForm(request.POST, author=request.user)
if creationform.is_valid():
creationform.save(commit=False)
creationform.save_m2m()
listing = creationform.instance
messages.success(request, "New Listing Created")
return redirect(reverse('main:listingdetails', kwargs={'pk': listing.idtag}))
else:
messages.error(request, 'Please correct the error below.')
creationform = ListingForm
return render(request,
"main/createlisting.html",
context={"creationform":creationform})
Form:
class ListingForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.author = kwargs.pop('author', None)
super(ListingForm, self).__init__(*args, **kwargs)
currencyList = (("USD", "US Dollars"),
("GBP", "Pounds"))
currency = forms.ChoiceField(choices=currencyList)
def save(self, commit=True):
listing = super(ListingForm, self).save(commit=False)
listing.author = self.author
if commit:
listing.save()
class Meta:
model = Listing
fields = ('title', 'description', 'price', 'currency', 'tags')
Traceback:
The above exception (invalid literal for int() with base 10: 'U') was the direct cause of the following exception:
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "C:\Users\-\Downloads\zephyrus\main\views.py", line 102, in createview
creationform.save_m2m()
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\forms\models.py", line 451, in _save_m2m
f.save_form_data(self.instance, cleaned_data[f.name])
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related.py", line 1668, in save_form_data
getattr(instance, self.attname).set(data)
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related_descriptors.py", line 1007, in set
else self.target_field.get_prep_value(obj)
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related.py", line 977, in get_prep_value
return self.target_field.get_prep_value(value)
File "C:\Users\-\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\__init__.py", line 1825, in get_prep_value
raise e.__class__(
Exception Type: ValueError at /listing/create/
Exception Value: Field 'id' expected a number but got 'U'.
Thanks for any help.

Django REST Framework: AttributeError: 'DeferredAttribute' object has no attribute 'isoformat'

This is my first time using Django REST FRAMEWORK, I'm facing an issue with a registration api, on the first try the api worked properly, but on the following tries it started throwing this error
AttributeError: 'DeferredAttribute' object has no attribute 'isoformat'
first here is my code:
serializers.py:
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = User.objects.create(**validated_data)
user.set_password(validated_data['password'])
user.save()
# return dict(status=True, code=1)
return User
class Meta:
model = User
fields = ['phone', 'email', 'first_name', 'last_name', 'birth_date', 'gender', 'user_type', 'password',
'username']
extra_kwargs = {
"password": {"write_only": True}
}
apis.py:
class RegisterApi(CreateAPIView):
model = get_user_model()
permission_classes = [permissions.AllowAny]
serializer_class = UserSerializer
models.py:
class User(AbstractUser):
notification_token = models.CharField(max_length=255, unique=True, blank=True, null=True)
phone = models.CharField(
_("Phone Number"),
max_length=50,
validators=[phone_validator],
unique=True,
)
is_active = models.BooleanField(
_('active'),
default=False,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
photo = models.ImageField(
_('Profile Picture'),
upload_to='profile/',
help_text=_(
"the user's profile picture."
),
blank=True,
null=True
)
address = models.CharField(_("Address"), max_length=255)
lives_in = models.ForeignKey('City', on_delete=do_nothing, null=True, blank=True)
user_type = models.CharField(
_("Type"),
max_length=3,
choices=USER_TYPES,
help_text=_("The user's type can be one of the available choices, "
"refer to the Model class for the detailed list."),
)
birth_date = models.DateField(_('Birth Date'), blank=True, null=True)
gender = models.CharField(choices=GENDERS, max_length=1, default='M')
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["first_name", "last_name", 'user_type', 'phone', 'email']
#property
def get_age(self) -> int:
today = date.today()
dob = self.birth_date
before_dob = (today.month, today.day) < (dob.month, dob.day)
return today.year - self.birth_date.year - before_dob
#property
def confirmed_phone(self) -> bool:
return False
#property
def confirmed_email(self) -> bool:
return False
def __str__(self):
return self.phone
now when i post
i get this error:
Internal Server Error: /api/register/
Traceback (most recent call last):
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\views.py", line 476, in raise_uncaught_exception
raise exc
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\generics.py", line 190, in post
return self.create(request, *args, **kwargs)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\mixins.py", line 20, in create
headers = self.get_success_headers(serializer.data)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\serializers.py", line 562, in data
ret = super().data
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\serializers.py", line 260, in data
self._data = self.to_representation(self.instance)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\serializers.py", line 529, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "C:\Users\Simou\Desktop\Work\IT-GDS\Resto\web\restaurant\venv\lib\site-packages\rest_framework\fields.py", line 1327, in to_representation
return value.isoformat()
AttributeError: 'DeferredAttribute' object has no attribute 'isoformat'
Knowing that the users are being registered in the database, but the response is throwing this error.
any help is appreciated.
You should return user instance from create() method, not User class:
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = User.objects.create(**validated_data)
user.set_password(validated_data['password'])
user.save()
# return dict(status=True, code=1)
return user # instead of User

Django Rest Framework: AttributeError: 'NoneType' object has no attribute '_meta' [for OneToOneField]

I need help with a POST request using Django rest framework.
I have a User model that inherits from AbstractBaseUser which has 2 fields: name and email.
Then I have a DojoMaster model that has a OneToOne relationship with the User model:
class DojoMaster(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
phone = models.BigIntegerField()
country = models.ForeignKey(Country, on_delete=models.CASCADE)
I want to register the dojo master via an API so I created the following serializers:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('name', 'email', 'password')
class DojoMasterCreateSerializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = DojoMaster
fields = ('user', 'phone', 'country')
def create(self, validated_data):
validated_data['country'] = Country.objects.get(
country=validated_data['country'])
user_data = validated_data.pop('user')
user = UserSerializer.create(UserSerializer(), validated_data=user_data)
subscriber, created = DojoMaster.objects.update_or_create(user=user,
phone = validated_data.pop('phone'),
country = validated_data['country'])
return subscriber
To call on these serializers, I created the following view:
class DojoMasterCreateView(generics.CreateAPIView):
def post(self, request, format='json'):
serializer = DojoMasterCreateSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
For the body of the POST request I had the following:
{
"user": {
"name": "XYZ",
"email": "xyz#mail.com",
"password": "8Xa,9Lv&"
},
"phone": 9696510,
"country": "USA"
}
However, when I do that I get the following error:
Traceback (most recent call last):
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
response = get_response(request)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\django\views\decorators\csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\django\views\generic\base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\views.py", line 494, in dispatch
response = self.handle_exception(exc)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\views.py", line 454, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\views.py", line 491, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\app_dev\development\GOQ\dojomaster_api\views.py", line 29, in post
if serializer.is_valid(raise_exception=ValueError):
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 236, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 435, in run_validation
value = self.to_internal_value(data)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 465, in to_internal_value
validated_value = field.run_validation(primitive_value)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 437, in run_validation
self.run_validators(value)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\fields.py", line 533, in run_validators
for validator in self.validators:
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\fields.py", line 392, in validators
self._validators = self.get_validators()
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 1460, in get_validators
self.get_unique_for_date_validators()
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\serializers.py", line 1502, in get_unique_for_date_validators
info = model_meta.get_field_info(self.Meta.model)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\utils\model_meta.py", line 39, in get_field_info
forward_relations = _get_forward_relationships(opts)
File "C:\Users\app_dev\Envs\game_of_quarks\lib\site-packages\rest_framework\utils\model_meta.py", line 96, in _get_forward_relationships
not field.remote_field.through._meta.auto_created
AttributeError: 'NoneType' object has no attribute '_meta'
I cannot figure out what the problem is. Help would be much appreciated.
serializer.is_valid method accepts keyword argument raise_exception. And its value should be true or false. By default it is false. If it is true, the exception will be auto triggered.
change your serializer.is_valid(raise_exception=ValueError) to serializer.is_valid().
And also for saving the serializer you should call the save method not the create method
class DojoMasterCreateView(generics.CreateAPIView):
def post(self, request, format='json'):
serializer = DojoMasterCreateSerializer(data=request.data)
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)
or in simple form
class DojoMasterCreateView(generics.CreateAPIView):
def post(self, request, format='json'):
serializer = DojoMasterCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
And i have no idea what user = UserSerializer.create(UserSerializer(), validated_data=user_data) means or create method logic is doing. If you want to save the user data, then follow the code given beloe
class DojoMasterCreateSerializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = DojoMaster
fields = ('user', 'phone', 'country')
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
subscriber, created = DojoMaster.objects.update_or_create(user=user, **validated_data)
return subscriber
And the json should contain the id of the country, like
{
"user": {
"name": "XYZ",
"email": "xyz#mail.com",
"password": "8Xa,9Lv&"
},
"phone": 9696510,
"country": 1
}

Django Rest Framework not working with simple nested serializer

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.

Django Rest Framework writable nested serializer raises AttributeError

I'm working on a Django based shipment management application. We have integrated the Django Rest Framework and exposed few end points.
Now the django app called "port_manager" has following models...
models.py
from location.models import CountryList, DistrictList
class PortList(models.Model):
name = models.CharField(max_length=45)
countryList_id = models.ForeignKey(CountryList, models.SET_NULL, blank=True, null=True, verbose_name='related country')
iso_code = models.CharField(max_length=10)
short_code = models.CharField(max_length=10, null=True, blank=True)
status = models.BooleanField(default=True)
def __str__(self):
return self.name
class PortDetail(models.Model):
port = models.OneToOneField(PortList, models.CASCADE, verbose_name='related port', primary_key=True)
phone = models.CharField(max_length=15)
district_list_id = models.ForeignKey(DistrictList, models.SET_NULL, blank=True, null=True,
verbose_name='related district')
email = models.EmailField()
fax = models.CharField(max_length=100, null=True, blank=True)
address = models.TextField()
map_location = models.CharField(max_length=45, null=True, blank=True)
other_information = models.TextField(null=True, blank=True)
current_pricing = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.port.name+' Details'
serializers.py
from rest_framework import serializers
from port_manager.models import PortList, PortDetail
from location.models import CountryList, DistrictList
class PortListSerializer(serializers.ModelSerializer):
countryList_id = serializers.PrimaryKeyRelatedField(queryset=CountryList.objects.all(), write_only=True)
class Meta:
model = PortList
fields = ('name', 'countryList_id', 'iso_code')
class PortDetailSerializer(serializers.ModelSerializer):
district_list_id = serializers.PrimaryKeyRelatedField(queryset=DistrictList.objects.all(),)
class Meta:
model = PortDetail
fields = ('port', 'phone', 'district_list_id', 'email', 'fax', 'address',
'map_location', 'other_information', 'current_pricing')
class PortSerializer(serializers.ModelSerializer):
port = PortListSerializer()
district_list_id = serializers.PrimaryKeyRelatedField(queryset=DistrictList.objects.all(), write_only=True)
class Meta:
model = PortDetail
def create(self, validated_data):
port_data = validated_data.pop('port')
port = PortList.objects.create(**port_data)
PortDetail.objects.create(port=port, **validated_data)
return PortDetail
Now when I POST to the end point using CURL it inserts into both of the tables in the database but raise error(400)
curl sample POST request
curl -H "Authorization: Token afab77f7c9320d396442eb1aef9a3bd5de54c3ce" -X POST -d '{"port":{"name":"Singapore", "countryList_id":"3", "iso_code":"SIN", "short_code":"898"},"district_list_id":"9", "email":"asd#aassd.com", "fax":"23423432", "other_information":"adasd sdas", "address":"asdas asd", "phone":"123412312"}' http://example.org/api/v1/portcombined/
Full stack from Django error log:
Internal Server Error: /api/v1/portcombined/
Traceback (most recent call last):
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.5/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/rest_framework/decorators.py", line 53, in handler
return func(*args, **kwargs)
File "/home/gpsl/sites/container/src/port_manager/views.py", line 143, in port_merged
return JSONResponse(serializer.data, status=201)
File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/usr/local/lib/python3.5/site-packages/rest_framework/serializers.py", line 463, in to_representation
attribute = field.get_attribute(instance)
File "/usr/local/lib/python3.5/site-packages/rest_framework/relations.py", line 157, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/usr/local/lib/python3.5/site-packages/rest_framework/fields.py", line 80, in get_attribute
instance = getattr(instance, attr)
AttributeError: 'ForwardManyToOneDescriptor' object has no attribute 'countryList_id'
Thanks to you all for taking your time and go through all these.
The problem is that context is not passed to nested serializers. Your PortSerializer class should have an __init__ method and there you should explicitly pass context to your nested serializer. See the example below:
class PortSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(PortSerializer, self).__init__(*args, **kwargs)
self.fields['port'] = PortListSerializer(context=self.context)
I think, you should not use countryList_id modelfield. Because, by default Django return the id of the object with object_id.
If you rename your model with countryList and pass countryList from the API, the Django will surely get the CountryList object.

Categories

Resources