Skip to content

Commit

Permalink
Implement and use an IOError ignoring ManyRelatedField for images
Browse files Browse the repository at this point in the history
  • Loading branch information
akx committed Mar 22, 2016
1 parent 01331f3 commit 7762a7d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
6 changes: 5 additions & 1 deletion democracy/views/hearing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from democracy.views.hearing_comment import HearingCommentSerializer
from democracy.views.label import LabelSerializer
from democracy.views.section import SectionFieldSerializer
from democracy.views.utils import IOErrorIgnoringManyRelatedField

from .hearing_report import HearingReport

Expand Down Expand Up @@ -42,7 +43,10 @@ def get_queryset(self):

class HearingSerializer(serializers.ModelSerializer):
labels = LabelSerializer(many=True, read_only=True)
images = HearingImageSerializer.get_field_serializer(many=True, read_only=True)
images = HearingImageSerializer.get_field_serializer(
many=True, read_only=True,
many_field_class=IOErrorIgnoringManyRelatedField
)
sections = serializers.SerializerMethodField()
comments = HearingCommentSerializer.get_field_serializer(many=True, read_only=True)
commenting = EnumField(enum_type=Commenting)
Expand Down
6 changes: 4 additions & 2 deletions democracy/views/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from democracy.models import Hearing, Section, SectionImage
from democracy.utils.drf_enum_field import EnumField
from democracy.views.base import AdminsSeeUnpublishedMixin, BaseImageSerializer
from democracy.views.utils import IOErrorIgnoringManyRelatedField


class SectionImageSerializer(BaseImageSerializer):

class Meta:
model = SectionImage
fields = ['title', 'url', 'width', 'height', 'caption']
Expand All @@ -17,7 +17,9 @@ class SectionSerializer(serializers.ModelSerializer):
"""
Serializer for section instance.
"""
images = SectionImageSerializer.get_field_serializer(many=True, read_only=True)
images = SectionImageSerializer.get_field_serializer(
many=True, read_only=True, many_field_class=IOErrorIgnoringManyRelatedField
)
type = serializers.SlugRelatedField(slug_field='identifier', read_only=True)
type_name_singular = serializers.SlugRelatedField(source='type', slug_field='name_singular', read_only=True)
type_name_plural = serializers.SlugRelatedField(source='type', slug_field='name_plural', read_only=True)
Expand Down
24 changes: 24 additions & 0 deletions democracy/views/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from functools import lru_cache

from django.db.models.query import QuerySet
from rest_framework import serializers
from rest_framework.relations import ManyRelatedField, MANY_RELATION_KWARGS

Expand Down Expand Up @@ -35,3 +36,26 @@ def get_field_serializer_class(cls, many_field_class=ManyRelatedField):
def get_field_serializer(cls, **kwargs):
many_field_class = kwargs.pop("many_field_class", ManyRelatedField)
return cls.get_field_serializer_class(many_field_class=many_field_class)(**kwargs)


class IOErrorIgnoringManyRelatedField(ManyRelatedField):
"""
A ManyRelatedField that ignores IOErrors occurring during iterating the children.
This is mainly useful for images that are referenced in the database but do not exist
on the server (where constructing them requires accessing them to populate the width
and height fields).
"""
def to_representation(self, iterable):
out = []
if isinstance(iterable, QuerySet):
iterable = iterable.iterator()
while True:
try:
value = next(iterable)
out.append(self.child_relation.to_representation(value))
except StopIteration:
break
except IOError:
continue
return out

0 comments on commit 7762a7d

Please sign in to comment.