A have a chain of OneToMany relations (one) Construction -> Camera -> Frame -> Event
models.py
def name_image(instance, filename):
return '/'.join(['images', str(instance.name), filename])
class Construction(models.Model):
""" Объект строительства"""
developer = models.ForeignKey(
Developer, related_name="constructions", on_delete=models.CASCADE
)
name = models.CharField(max_length=100)
plan_image = models.ImageField(upload_to=name_image, blank=True, null=True)
address = models.CharField(max_length=100)
coordinates = models.PointField(blank=True)
deadline = models.DateTimeField(default=timezone.now, )
workers_number = models.IntegerField(default=0)
machines_number = models.IntegerField(default=0)
def __str__(self):
return self.name
class Camera(models.Model):
building = models.ForeignKey( # not important
Construction, related_name="cameras", on_delete=models.CASCADE
)
name = models.CharField(max_length=100)
url = models.CharField(max_length=100)
...
class Frame(models.Model):
""" Фото с камеры """
camera_id = models.ForeignKey(
Camera, related_name="frames", on_delete=models.CASCADE
)
...
class Event(models.Model):
frame_id = models.ForeignKey(
Frame, related_name="events", on_delete=models.CASCADE
)
...
I want to output data about Camera in EventSerializer (GET method). I am using get_construction method I want to use ConstructionSerializer for Construction object ( <class ‘api_buildings.models.Construction’>)
But I have an error
Object of type BoundField is not JSON serializable
How can I fix this error (I know, that I can use model_to_dict, but I want to use ConstructionSerializer)
class EventSerializer(serializers.ModelSerializer):
time = serializers.DateTimeField(format=TIME_FORMAT)
camera = serializers.SerializerMethodField()
construction = serializers.SerializerMethodField()
frame = serializers.SerializerMethodField()
developer = serializers.SerializerMethodField()
class Meta:
model = Event
fields = (
'id', 'frame_id', 'frame', 'developer', 'camera', 'construction', 'type_of_event', 'class_name',
'grn', 'track_id', 'bounding_coords', 'time'
)
def create(self, validated_data):
instance = super().create(validated_data=validated_data)
return instance
def get_construction(self, obj):
buiding = obj.frame_id.camera_id.building
print(type(buiding)) # <class 'api_buildings.models.Construction'>
return ConstructionSerializer(buiding)
Full error log (may be usefull)
Internal Server Error: /api/events/
Traceback (most recent call last):
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 204, in _get_response
response = response.render()
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/django/template/response.py", line 105, in render
self.content = self.rendered_content
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/djangorestframework_camel_case/render.py", line 17, in render
camelize(data, **api_settings.JSON_UNDERSCOREIZE), *args, **kwargs
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/renderers.py", line 724, in render
context = self.get_context(data, accepted_media_type, renderer_context)
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/renderers.py", line 680, in get_context
'content': self.get_content(renderer, data, accepted_media_type, renderer_context),
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/renderers.py", line 413, in get_content
content = renderer.render(data, accepted_media_type, renderer_context)
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/djangorestframework_camel_case/render.py", line 10, in render
camelize(data, **api_settings.JSON_UNDERSCOREIZE), *args, **kwargs
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/renderers.py", line 103, in render
allow_nan=not self.strict, separators=separators
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/utils/json.py", line 25, in dumps
return json.dumps(*args, **kwargs)
File "/home/alex/anaconda3/lib/python3.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 201, in encode
chunks = list(chunks)
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 431, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 325, in _iterencode_list
yield from chunks
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 438, in _iterencode
o = _default(o)
File "/home/alex/root_folder/projects/38_safe_building/1_code/buildings/back/api/venv/lib/python3.7/site-packages/rest_framework/utils/encoders.py", line 67, in default
return super().default(obj)
File "/home/alex/anaconda3/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type BoundField is not JSON serializable
Advertisement
Answer
Seems you forgot to use .data:
return ConstructionSerializer(buiding).data