|
|
@ -5,6 +5,8 @@ from apps.course.models import Course, CourseCategory, Attachment, Glossary, Les |
|
|
from apps.course.models.course import get_localized_field |
|
|
from apps.course.models.course import get_localized_field |
|
|
from apps.chat.models import RoomMessage |
|
|
from apps.chat.models import RoomMessage |
|
|
from apps.account.serializers import UserProfileSerializer |
|
|
from apps.account.serializers import UserProfileSerializer |
|
|
|
|
|
import ast |
|
|
|
|
|
import json |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -413,25 +415,62 @@ class CourseDetailSerializer(serializers.ModelSerializer): |
|
|
def get_status(self, obj): |
|
|
def get_status(self, obj): |
|
|
return get_localized_field(self._lang(), obj.status) |
|
|
return get_localized_field(self._lang(), obj.status) |
|
|
|
|
|
|
|
|
def get_timing(self, obj): |
|
|
|
|
|
import json |
|
|
|
|
|
val = get_localized_field(self._lang(), obj.timing) |
|
|
|
|
|
if isinstance(val, str): |
|
|
|
|
|
|
|
|
def _parse_builder_payload(self, value): |
|
|
|
|
|
if value is None: |
|
|
|
|
|
return None |
|
|
|
|
|
if isinstance(value, str): |
|
|
|
|
|
for parser in (json.loads, ast.literal_eval): |
|
|
try: |
|
|
try: |
|
|
return json.loads(val) |
|
|
|
|
|
|
|
|
parsed = parser(value) |
|
|
|
|
|
return parsed |
|
|
except Exception: |
|
|
except Exception: |
|
|
pass |
|
|
|
|
|
return val |
|
|
|
|
|
|
|
|
continue |
|
|
|
|
|
return value |
|
|
|
|
|
return value |
|
|
|
|
|
|
|
|
|
|
|
def _extract_builder_list(self, value): |
|
|
|
|
|
""" |
|
|
|
|
|
Return the raw builder list for the current language. |
|
|
|
|
|
Supports both: |
|
|
|
|
|
- direct lists like [{'day': 'monday', 'timing': '12:22'}, ...] |
|
|
|
|
|
- multilingual wrappers like [{'language_code': 'en', 'title': "[...]"}, ...] |
|
|
|
|
|
""" |
|
|
|
|
|
parsed = self._parse_builder_payload(value) |
|
|
|
|
|
if parsed is None: |
|
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
|
|
if isinstance(parsed, list) and parsed: |
|
|
|
|
|
if all(isinstance(item, dict) and 'language_code' in item for item in parsed): |
|
|
|
|
|
current_lang = self._lang() |
|
|
|
|
|
selected = next( |
|
|
|
|
|
( |
|
|
|
|
|
item for item in parsed |
|
|
|
|
|
if isinstance(item, dict) and item.get('language_code') == current_lang |
|
|
|
|
|
), |
|
|
|
|
|
parsed[0], |
|
|
|
|
|
) |
|
|
|
|
|
parsed = self._parse_builder_payload( |
|
|
|
|
|
selected.get('title') |
|
|
|
|
|
or selected.get('text') |
|
|
|
|
|
or selected.get('value') |
|
|
|
|
|
or selected.get('name') |
|
|
|
|
|
or [] |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
if isinstance(parsed, list): |
|
|
|
|
|
return parsed |
|
|
|
|
|
if isinstance(parsed, dict): |
|
|
|
|
|
if isinstance(parsed.get('list'), list): |
|
|
|
|
|
return parsed['list'] |
|
|
|
|
|
if isinstance(parsed.get('items'), list): |
|
|
|
|
|
return parsed['items'] |
|
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
|
|
def get_timing(self, obj): |
|
|
|
|
|
return self._extract_builder_list(obj.timing) |
|
|
|
|
|
|
|
|
def get_features(self, obj): |
|
|
def get_features(self, obj): |
|
|
import json |
|
|
|
|
|
val = get_localized_field(self._lang(), obj.features) |
|
|
|
|
|
if isinstance(val, str): |
|
|
|
|
|
try: |
|
|
|
|
|
return json.loads(val) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
pass |
|
|
|
|
|
return val |
|
|
|
|
|
|
|
|
return self._extract_builder_list(obj.features) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|