Django REST Serializer uses wrong Model for serialization - django

Problem:
My serializer uses the wrong Model for serialization. I expected that the serializer uses my ProfileInfo model but it does not. It uses the User model. They have an OneToOneRelationship. I do not know why because I defined in the meta that the serializer should use the ProfileInfo model.
So when I try to serialize the username with -> username=serializers.Field(source='user.username') Django shows this error:
'User' object has no attribute 'user'.
Can you please explain to me why the wrong model is used ? Thank you for your help.
Serializers:
class ProfileInfoSerializer(serializers.ModelSerializer):
image = serializers.SerializerMethodField()
socialMediaLinks = serializers.SerializerMethodField("get_social_media_links")
username = serializers.Field(source='user.username')
class Meta:
model = ProfileInfo
fields = ['username', 'description', 'image', 'socialMediaLinks']
def get_image(self, obj):
request = self.context.get('request')
photo_url = obj.image.url
return request.build_absolute_uri(photo_url)
class UserInfoSerializer(serializers.ModelSerializer):
user = ProfileInfoSerializer()
wingman = ProfileInfoSerializer()
clan = ClanSerializer()
class Meta:
model = ProfileInfo
fields = ['user', 'clan', 'wingman']
Model:
class ProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
wingman = models.OneToOneField(User, on_delete=None, related_name="wingman", null=True)
clan = models.ForeignKey(Clan, on_delete=None)
image = models.ImageField(upload_to="", default="", null=True)
description = models.CharField(max_length=5000, null=True)
Api:
class ProfileInfoApi(APIView):
def get(self, request, id):
profileInfo = ProfileInfo.objects.get(pk=id)
serializer = UserInfoSerializer(profileInfo, context={'request': request})
return Response(serializer.data)
Traceback:
Internal Server Error: /api/profileInfo/1/
Traceback (most recent call last):
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "C:\_sources\Gamingplattform\Backend\gamingplattform\profileInfo\api.py", line 18, in get
return Response(serializer.data)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 560, in data
ret = super(Serializer, self).data
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 527, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\fields.py", line 570, in to_representation
field_name=self.field_name,
NotImplementedError: Field.to_representation() must be implemented for field username. If you do not need to support write operations you probably want to subclass `ReadOnlyField` instead.
Internal Server Error: /api/profileInfo/getFriends/1/
Traceback (most recent call last):
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\fields.py", line 441, in get_attribute
return get_attribute(instance, self.source_attrs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\fields.py", line 100, in get_attribute
instance = getattr(instance, attr)
AttributeError: 'User' object has no attribute 'user'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "C:\_sources\Gamingplattform\Backend\gamingplattform\profileInfo\api.py", line 36, in get
return Response(serializer.data)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 765, in data
ret = super(ListSerializer, self).data
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 683, in to_representation
self.child.to_representation(item) for item in iterable
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 683, in <listcomp>
self.child.to_representation(item) for item in iterable
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 527, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py", line 514, in to_representation
attribute = field.get_attribute(instance)
File "C:\Users\Aaron Visang\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\fields.py", line 462, in get_attribute
raise type(exc)(msg)
AttributeError: Got AttributeError when attempting to get a value for field `username` on serializer `ProfileInfoSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'user'.

You are trying to serialize ProfileInfo instances with UserInfoSerializer serializer, which is not possible. So
Change
serializer = UserInfoSerializer(profileInfo, context={'request': request})
to
serializer = ProfileInfoSerializer(profileInfo, context={'request': request})
Hence your view be like,
class ProfileInfoApi(APIView):
def get(self, request, id):
profileInfo = ProfileInfo.objects.get(pk=id)
serializer = ProfileInfoSerializer(profileInfo, context={'request': request})
return Response(serializer.data)
UPDATE-1It's NotImplementedError,You shouldn't use serializer.Field class unless you need to inherrit. So change
username = serializers.Field(source='user.username')
to
username = serializers.CharField(source='user.username')<br>
Apart from this update, I would like to inform that, you are defined one line as , socialMediaLinks = serializers.SerializerMethodField("get_social_media_links") But, there is no method named get_social_media_links. It will raise some error, sureSo the ProfileInfoSerializer should be as below
class ProfileInfoSerializer(serializers.ModelSerializer):
image = serializers.SerializerMethodField()
socialMediaLinks = serializers.SerializerMethodField("get_social_media_links")
username = serializers.CharField(source='user.username')
class Meta:
model = ProfileInfo
fields = ['username', 'description', 'image', 'socialMediaLinks']
def get_image(self, obj):
request = self.context.get('request')
photo_url = obj.image.url
return request.build_absolute_uri(photo_url)
def get_social_media_links(self, model):
return "some data"

Related

How do I properly deserialize data with django-money?

I have Model that contains MoneyField from djmoney
class Task(models.Model):
description = models.CharField(max_length=512)
user = models.ForeignKey("user.User", on_delete=models.CASCADE)
price = MoneyField(
max_digits=8,
decimal_places=2,
default_currency="USD",
default=0)
Serializer
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = "__all__"
read_only_fields = ("user",)
My APIView POST function of Viewset
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=201, headers=headers)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
When I'm trying to POST data in format like this
{
"description": "Test",
"price": "20.00"
}
It gives me an error, that
'decimal.Decimal' object has no attribute 'amount' with given Traceback.
How can I solve this issue?
Traceback (most recent call last):
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/home/user/PycharmProjects/my_project/tackapp/tack/views.py", line 37, in create
serializer.is_valid(raise_exception=True)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 227, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 426, in run_validation
value = self.to_internal_value(data)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 483, in to_internal_value
validated_value = field.run_validation(primitive_value)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/fields.py", line 569, in run_validation
self.run_validators(value)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/fields.py", line 593, in run_validators
validator(value)
File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/djmoney/models/validators.py", line 30, in __call__
cleaned = cleaned.amount
I did found workaround like this but I'm trying to get my code clean and simple. And I think that I am missing something.
So basically serializer expects value in Money object, but did not expect str from it's own serializer methods
def create(self, request, *args, **kwargs):
price = Money(request.data["price"], "USD")
serializer = self.get_serializer(data=request.data | {"price": price})
...

'collections.OrderedDict' object has no attribute 'uuid' - Django REST Framework

I'm using django-mptt to create a tree-like structure for my Section model. Unfortunately, when I go to serialize it with drf-writable-nested, I get an error. This error only occurs when the url field is added to the serializer.
Also, when I remove uuid from the custom lookup field, the error is just replaced with pk.
I found this: https://stackoverflow.com/a/55173445/9137820, but I'm not accessing any of the data directly, so I'm not sure how that could be the issue.
Code:
# models.py
class Section(MPTTModel, TimeStampedModel):
uuid = models.UUIDField(default=uuid_lib.uuid4, editable=False)
name = models.CharField(max_length=255, unique=True)
objects = TreeManager()
parent = TreeForeignKey('self', related_name='section_children', on_delete=models.CASCADE, null=True, blank=True)
# serializers.py
class SectionSerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
children = serializers.ListField(source='get_children', child=RecursiveField())
class Meta:
model = Section
fields = ['url', 'uuid', 'name', 'children']
extra_kwargs = {
'url': {'lookup_field': 'uuid'},
}
# views.py
class SectionDetail(generics.RetrieveUpdateDestroyAPIView, viewsets.GenericViewSet):
queryset = Section.objects.all()
serializer_class = SectionSerializer
lookup_field = 'uuid'
Traceback:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 75, in update
return Response(serializer.data)
File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 548, in data
ret = super().data
File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 246, in data
self._data = self.to_representation(self.instance)
File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 515, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 1661, in to_representation
return [self.child.to_representation(item) if item is not None else None for item in data]
File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 1661, in <listcomp>
return [self.child.to_representation(item) if item is not None else None for item in data]
File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 515, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/usr/local/lib/python3.9/site-packages/rest_framework/relations.py", line 399, in to_representation
url = self.get_url(value, self.view_name, request, format)
File "/usr/local/lib/python3.9/site-packages/rest_framework/relations.py", line 335, in get_url
lookup_value = getattr(obj, self.lookup_field)
Exception Type: AttributeError at /api/v1/sections/3b15cbda-f61e-4a00-89fb-817beed10b14/
Exception Value: 'collections.OrderedDict' object has no attribute 'uuid'
I did some digging and this is what I can find. Dictionaries and OrderedDicts don't save keys and values as class attributes. So you cant retrieve them using getattr(). You need to request a method or attribute like dict.keys() or dict.values() from the OrderedDict. You can't use a key name.
See this example:
from collections import OrderedDict
g = OrderedDict()
g['test'] = 1
g = getattr(g, 'values')
print(list(g())[0])
That works fine but if you changed
g = getattr(g, 'values')
to
g = getattr(g, 'test')
It produces the same error you're experiencing

Source in Meta.extra_kwargs do not add to fields

I have few django models:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
phone = models.CharField(
_('phone number'), max_length=16,
unique=True, blank=True, null=True,
default=None, validators=[phone_validator]
)
...
class UserExtension(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Meta:
abstract = True
class Worker(UserExtension):
# some fields
class Administrator(UserExtension):
# some fields
View:
class AdministratorListView(ListAPIView):
permission_classes = (AllowAny,)
queryset = Administrator.objects.all()
serializer_class = serializers.AdministratorSerializer
And serializer:
class AdministratorSerializer(serializers.ModelSerializer):
class Meta:
model = Administrator
fields = ('network', 'email')
extra_kwargs = {'email': {'source': 'user.email'}}
But this is not working. Following traceback tell about field does not exist for my model:
Traceback (most recent call last):
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 455, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 492, in dispatch
response = handler(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/generics.py", line 201, in get
return self.list(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/mixins.py", line 48, in list
return Response(serializer.data)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 765, in data
ret = super(ListSerializer, self).data
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 683, in to_representation
self.child.to_representation(item) for item in iterable
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 683, in <listcomp>
self.child.to_representation(item) for item in iterable
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 510, in to_representation
fields = self._readable_fields
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/utils/functional.py", line 37, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 376, in _readable_fields
field for field in self.fields.values()
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 363, in fields
for key, value in self.get_fields().items():
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1047, in get_fields
source, info, model, depth
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1192, in build_field
return self.build_unknown_field(field_name, model_class)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1304, in build_unknown_field
(field_name, model_class.__name__)
django.core.exceptions.ImproperlyConfigured: Field name `user.email` is not valid for model `Administrator`.
I looked at the source code and realized that the value from 'source' is passed to build_field as field_name argument and rest-framework simply cannot find this field ('user.email') in my model (Administrator)
part of get_fields method
build_field method

Django POST request issue with model

I have a model Condition that has a field symptoms, which takes multiple different Symptoms objects. Whenever, I make a POST request to create a Condition object, I get the following error:
'Condition: epilepsy' needs to have a value for field "condition" before this many-to-many relationship can be used.
The above 'Condition: epilepsy' is nested between <>, but theres a formatting issue with posting that.
Here is my Condition model:
class Condition(models.Model):
class Treatment():
SURGERY, NON_INVASIVE, PRESCRIPTION_MEDICINE, NONE = range(4)
CHOICES = (
(SURGERY, 'Surgery'),
(NON_INVASIVE, 'Non-Invasive Treatment'),
(PRESCRIPTION_MEDICINE, 'Prescription Medicine'),
(NONE, 'None')
)
class Medicalfield(models.Model):
ONCOLOGY, CARDIOLOGY, NEPHROLOGY, PEDIATRICS, ENDOCRONOLOGY, PSYCHOLOGY = range(6)
CHOICES = (
(ONCOLOGY, 'Oncology'),
(CARDIOLOGY, 'Cardiology'),
(NEPHROLOGY, 'Nephrology'),
(PEDIATRICS, 'Pediatrics'),
(ENDOCRONOLOGY, 'Endocronology'),
(PSYCHOLOGY, 'Psychology')
)
name = models.CharField(max_length=200)
contagious = models.BooleanField()
treatable = models.BooleanField()
treatment = models.IntegerField(choices=Treatment.CHOICES, null=True)
severeity = models.IntegerField(default=0)
symptoms = models.ManyToManyField('Symptom', blank=True)
medicalfield = models.IntegerField(choices=Medicalfield.CHOICES, null=True)
new = ConditionManager()
def __unicode__(self):
return u"%s" % ( self.name )
Here is my Serializer
class ConditionSerializer(serializers.ModelSerializer):
def create(self, validated_data):
attrs = validated_data
request = self.context['request']
return Condition.new.create_condition(**attrs)
class Meta:
model = Condition
fields = ('id', 'treatment', 'name', 'contagious', 'treatable', 'treatment', 'severeity', 'symptoms', 'medicalfield')
Here is the Manager
class ConditionManager(models.Manager):
use_in_migrations = True
use_for_related_fields=True
def create_condition(self, *args, **kwargs):
condition_obj = conditions.models.Condition(name=kwargs['name'], contagious=kwargs['contagious'], treatable=kwargs['treatable'], treatment=kwargs['treatment'], severeity=kwargs['severeity'], symptoms=kwargs['symptoms'], medicalfield=kwargs['medicalfield'])
condition_obj.save()
return condition_obj
And here is the View
#api_view(['POST'])
#permission_classes((AllowAny, ))
def create_condition(request):
context = {'request': request}
symptoms = request.data['symptoms']
symptoms = Symptom.objects.filter(name__in=symptoms)
s = []
for symptom in symptoms:
s.append(symptom.pk)
request.data['symptoms'] = s
serializer = ConditionSerializer(data=request.data, context=context)
if serializer.is_valid():
serializer.save()
return response.Response(serializer.data, status=201)
return response.Response(serializer.errors, status=400)
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 477, in dispatch
response = self.handle_exception(exc)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 437, in handle_exception
self.raise_uncaught_exception(exc)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 474, in dispatch
response = handler(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/decorators.py", line 52, in handler
return func(*args, **kwargs)
File "/Users/user/medicalrecords/conditions/views.py", line 28, in create_condition
serializer.save()
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/Users/user/medicalrecords/conditions/serializers.py", line 24, in create
return Condition.new.create_condition(**attrs)
File "/Users/user/medicalrecords/conditions/managers.py", line 17, in create_condition
condition_obj = conditions.models.Condition(name=kwargs['name'], contagious=kwargs['contagious'], treatable=kwargs['treatable'], treatment=kwargs['treatment'], severeity=kwargs['severeity'], symptoms=kwargs['symptoms'], medicalfield=kwargs['medicalfield'])
File "/Library/Python/2.7/site-packages/django/db/models/base.py", line 550, in __init__
setattr(self, prop, kwargs[prop])
File "/Library/Python/2.7/site-packages/django/db/models/fields/related_descriptors.py", line 499, in __set__
manager = self.__get__(instance)
File "/Library/Python/2.7/site-packages/django/db/models/fields/related_descriptors.py", line 476, in __get__
return self.related_manager_cls(instance)
File "/Library/Python/2.7/site-packages/django/db/models/fields/related_descriptors.py", line 783, in __init__
(instance, self.source_field_name))
ValueError: "<Condition: epilepsy>" needs to have a value for field "condition" before this many-to-many relationship can be used.
[22/Feb/2017 20:01:45] "POST /conditions/new/condition/ HTTP/1.1" 500 15799
traceback from #snakefcz 's answer
Internal Server Error: /conditions/new/condition/
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 477, in dispatch
response = self.handle_exception(exc)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 437, in handle_exception
self.raise_uncaught_exception(exc)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 474, in dispatch
response = handler(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/decorators.py", line 52, in handler
return func(*args, **kwargs)
File "/Users/user/medicalrecords/conditions/views.py", line 45, in create_condition
return response.Response(serializer.data, status=201)
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 527, in data
ret = super(Serializer, self).data
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 496, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 643, in to_representation
self.child.to_representation(item) for item in iterable
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 479, in to_representation
fields = self._readable_fields
File "/Library/Python/2.7/site-packages/django/utils/functional.py", line 35, in get
res = instance.dict[self.name] = self.func(instance)
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 373, in _readable_fields
field for field in self.fields.values()
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 359, in fields
for key, value in self.get_fields().items():
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 1010, in get_fields
fields[field_name] = field_class(**field_kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/fields.py", line 733, in init
super(CharField, self).init(**kwargs)
TypeError: init() got an unexpected keyword argument 'view_name'
You'll need to create a Symptom serializer in addition to the Condition one. Your ConditionSerializer should look something like:
class ConditionSerializer(serializers.ModelSerializer):
symptoms = SymptomSerializer(read_only=True, many=True, allow_null=True)
class Meta:
model = Condition
fields = ('id', 'treatment', 'name', 'contagious', 'treatable', 'treatment', 'severeity', 'symptoms', 'medicalfield')
def create(self, validated_data):
attrs = validated_data
request = self.context['request']
return Condition.new.create_condition(**attrs)
## Try it
#api_view(['POST'])
#permission_classes((AllowAny, ))
def create_condition(request):
context = {'request': request}
serializer = ConditionSerializer(data=request.data, context=context)
if serializer.is_valid():
condition = serializer.save()
symptoms = request.data['symptoms']
for symp in symptoms:
symptom = Symptom.objects.get(id=symp) ## if it's id's you are passing
condition.symptoms.add(symptom)
return response.Response(serializer.data, status=201)
return response.Response(serializer.errors, status=400)

Serializer results in KeyError after correct data input and save

I'm creating an API endpoint that works and saves data through its API. It works, but my concern is that it throws a KeyError as shown below. I'm not sure if this is an issue with my code. Your help is very much appreciated.
Data:
data = {'title': u'abc', 'career_level': 1}
Serializer:
class JobPostSerializer(serializers.ModelSerializer):
career_level = PrimaryKeyRelatedField(allow_null=True, queryset=CareerLevel.objects.all(), required=False)
title = CharField(allow_blank=True, allow_null=True, max_length=240, required=False)
Model:
class JobPost(models.Model):
career_level = models.ForeignKey(CareerLevel, related_name='jobpost_career', blank=True, null=True)
title = models.CharField(max_length=240, blank=True, null=True)
created_at = models.DateTimeField(db_index=True, auto_now_add=True)
def __str__(self):
return self.title
def __unicode__(self):
return self.title
class Meta:
ordering = ['-created_at']
Error Message:
Internal Server Error: /api/v1/posts/
Traceback (most recent call last):
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/viewsets.py", line 87, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 22, in create
headers = self.get_success_headers(serializer.data)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 241, in data
self._data = self.to_representation(self.validated_data)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 463, in to_representation
attribute = field.get_attribute(instance)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/relations.py", line 157, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/fields.py", line 78, in get_attribute
instance = instance[attr]
KeyError: u'career_level'
Your serializer definition makes no sense.
JobPostSerializer(data={'title': u'abc', 'career_level': 1}):
It should instead be:
class JobPostSerializer(serializers.ModelSerializer):
That line of yours is more similar to when you want to instantiate the serializer. Something like when you want to check if the input was valid, for example.
job_serializer = JobPostSerializer(data={'title': u'abc', 'career_level': 1})
job_serializer.is_valid()