(self, obj)
| 103 | """Rich serializer for program detail view — extends slim serializer with full custom_properties.""" |
| 104 | |
| 105 | def to_representation(self, obj): |
| 106 | data = super().to_representation(obj) |
| 107 | cp = obj.custom_properties or {} |
| 108 | |
| 109 | # Categories |
| 110 | data['categories'] = cp.get('categories') or [] |
| 111 | |
| 112 | # Content rating |
| 113 | data['rating'] = cp.get('rating') |
| 114 | data['rating_system'] = cp.get('rating_system') |
| 115 | |
| 116 | # Star ratings |
| 117 | data['star_ratings'] = cp.get('star_ratings') or [] |
| 118 | |
| 119 | # Credits — flatten from XMLTV structure |
| 120 | credits = cp.get('credits') or {} |
| 121 | data['credits'] = { |
| 122 | 'actors': credits.get('actor') or [], |
| 123 | 'directors': credits.get('director') or [], |
| 124 | 'writers': credits.get('writer') or [], |
| 125 | 'producers': credits.get('producer') or [], |
| 126 | 'presenters': credits.get('presenter') or [], |
| 127 | } |
| 128 | |
| 129 | # Video/audio quality |
| 130 | video = cp.get('video') or {} |
| 131 | data['video_quality'] = video.get('quality') |
| 132 | data['aspect_ratio'] = video.get('aspect') |
| 133 | |
| 134 | audio = cp.get('audio') or {} |
| 135 | data['stereo'] = audio.get('stereo') |
| 136 | |
| 137 | # Previously shown (rerun) |
| 138 | data['is_previously_shown'] = bool(cp.get('previously_shown')) |
| 139 | |
| 140 | # Geographic/language |
| 141 | data['country'] = cp.get('country') |
| 142 | data['language'] = cp.get('language') |
| 143 | |
| 144 | # Dates |
| 145 | data['production_date'] = cp.get('date') |
| 146 | previously_shown = cp.get('previously_shown_details') or {} |
| 147 | data['original_air_date'] = previously_shown.get('start') |
| 148 | |
| 149 | # Content advisory (SD) |
| 150 | data['content_advisory'] = cp.get('content_advisory') or [] |
| 151 | |
| 152 | # Full content ratings array (SD — all regional ratings) |
| 153 | data['content_ratings'] = cp.get('content_ratings') or [] |
| 154 | |
| 155 | # Sports event details (SD) |
| 156 | data['event_details'] = cp.get('event_details') |
| 157 | |
| 158 | # Runtime (duration without commercials) |
| 159 | length = cp.get('length') or {} |
| 160 | data['runtime'] = length.get('value') if length else None |
| 161 | data['runtime_units'] = length.get('units') if length else None |
| 162 |
nothing calls this directly
no test coverage detected