Newer
Older
class NoteLinkSerializer(serializers.ModelSerializer):
type_id = serializers.PrimaryKeyRelatedField(queryset=LinkType.objects.all(), source="type")
class Meta:
model = NoteLink
fields = ("type_id", "url")
tags_json_schema = {"type": "array", "items": {"type": "string"}}
class NoteSerializer(serializers.ModelSerializer):
contributor_ids = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Profile.objects.all(),
required=False,
source="contributors",
help_text="`Profile` IDs that contributed to this episode.",
)
image_id = serializers.PrimaryKeyRelatedField(
queryset=Image.objects.all(),
required=False,
allow_null=True,
source="image",
help_text="`Image` ID.",
language_ids = serializers.PrimaryKeyRelatedField(
allow_null=True,
many=True,
queryset=Language.objects.all(),
required=False,
source="language",
help_text="Array of `Language` IDs.",
links = NoteLinkSerializer(many=True, required=False, help_text="Array of `Link` objects.")
playlist_id = serializers.IntegerField(required=False, help_text="Array of `Playlist` IDs.")
tags = JSONSchemaField(tags_json_schema, required=False, help_text="Tags of the Note.")
timeslot_id = serializers.PrimaryKeyRelatedField(
queryset=TimeSlot.objects.all(),
required=False,
source="timeslot",
help_text="`Timeslot` ID.",
topic_ids = serializers.PrimaryKeyRelatedField(
allow_null=True,
many=True,
queryset=Topic.objects.all(),
required=False,
source="topic",
help_text="Array of `Topic`IDs.",
class Meta:
model = Note
"created_at",
"created_by",
"updated_at",
"updated_by",
)
"contributor_ids",
"language_ids",
def create(self, validated_data):
"""Create and return a new Note instance, given the validated data."""
links_data = validated_data.pop("links", [])
show = validated_data["timeslot"].schedule.show
user = self.context.get("request").user
user_is_owner = user in show.owners.all()
# Having the create_note permission overrides the ownership
if not (
user.has_perm("program.create_note")
or (user.has_perm("program.add_note") and user_is_owner)
):
raise exceptions.PermissionDenied(detail="You are not allowed to create this note.")
# we derive `contributors`, `language` and `topic` from the Show's values if not set
contributors = validated_data.pop("contributors", show.hosts.values_list("id", flat=True))
language = validated_data.pop("language", show.language.values_list("id", flat=True))
topic = validated_data.pop("topic", show.topic.values_list("id", flat=True))
validated_data["image"] = validated_data.pop("image", None)

Ernesto Rico Schmidt
committed
try:
note = Note.objects.create(
created_by=self.context.get("request").user.username,
**validated_data,
)
except IntegrityError:
raise exceptions.ValidationError(
code="duplicate", detail="note for this timeslot already exists."
)
else:
note.contributors.set(contributors)
note.language.set(language)
note.topic.set(topic)

Ernesto Rico Schmidt
committed
# optional nested objects
for link_data in links_data:
NoteLink.objects.create(note=note, **link_data)

Ernesto Rico Schmidt
committed
note.save()

Ernesto Rico Schmidt
committed
return note
def update(self, instance, validated_data):
"""Update and return an existing Note instance, given the validated data."""
user = self.context.get("request").user
user_is_owner = user in instance.timeslot.schedule.show.owners.all()
# Having the update_note permission overrides the ownership
if not (
user.has_perm("program.update_note")
or (user.has_perm("program.change_note") and user_is_owner)
):
raise exceptions.PermissionDenied(detail="You are not allowed to update this note.")
if "cba_id" in validated_data:
instance.cba_id = validated_data.get("cba_id")
if "content" in validated_data:
instance.content = validated_data.get("content")
if "image" in validated_data:
instance.image = validated_data.get("image")
if "summary" in validated_data:
instance.summary = validated_data.get("summary")
if "timeslot" in validated_data:
instance.timeslot = validated_data.get("timeslot")
if "tags" in validated_data:
instance.tags = validated_data.get("tags")
if "title" in validated_data:
instance.title = validated_data.get("title")
# optional many-to-many
if "contributors" in validated_data:
instance.contributors.set(validated_data.get("contributors", []))
if "language" in validated_data:
instance.language.set(validated_data.get("language", []))
# Only update this field if the user has the update_note permission, ignore otherwise
if "topic" in validated_data and user.has_perm("program.update_note"):
instance.topic.set(validated_data.get("topic", []))
if "links" in validated_data:
instance = update_links(instance, validated_data.get("links"))
instance.updated_by = self.context.get("request").user.username
instance.save()

jackie / Andrea Ida Malkah Klaura
committed
return instance
class RadioSettingsSerializer(serializers.ModelSerializer):
cba = serializers.SerializerMethodField()
image_requirements = serializers.SerializerMethodField()
playout = serializers.SerializerMethodField()
program = serializers.SerializerMethodField()
station = serializers.SerializerMethodField()
class Meta:
fields = read_only_fields = (
"id",
"cba",
"image_requirements",
"playout",
"program",
def get_cba(self, obj) -> RadioCBASettings:
if self.context.get("request").user.is_authenticated:
return RadioCBASettings(
api_key=obj.cba_api_key,
domains=obj.cba_domains,
)
return RadioCBASettings(domains=obj.cba_domains)
@staticmethod
def get_image_requirements(obj) -> RadioImageRequirementsSettings:
def get_aspect_ratio(field) -> tuple[int, int] | tuple[float, float]:
"""return the tuple of ints or floats representing the aspect ratio of the image."""
values = field.split(":")
try:
return int(values[0]), int(values[1])
except ValueError:
return float(values[0]), float(values[1])
aspect_ratios = {
"note.image": get_aspect_ratio(obj.note_image_aspect_ratio),
"profile.image": get_aspect_ratio(obj.profile_image_aspect_ratio),
"show.image": get_aspect_ratio(obj.show_image_aspect_ratio),
"show.logo": get_aspect_ratio(obj.show_logo_aspect_ratio),
"aspect_ratio": aspect_ratios["note.image"],
"shape": obj.profile_image_shape,
"aspect_ratio": aspect_ratios["profile.image"],
"shape": obj.profile_image_shape,
}
},
"show.image": {
"frame": {
"aspect_ratio": aspect_ratios["show.image"],
"shape": obj.profile_image_shape,
}
},
"show.logo": {
"frame": {
"aspect_ratio": aspect_ratios["show.logo"],
"shape": obj.profile_image_shape,
}
},
}
def get_program(obj) -> RadioProgramSettings:
return RadioProgramSettings(
micro=MicroProgram(show_id=obj.micro_show.id if obj.micro_show else None),
fallback=ProgramFallback(
show_id=obj.fallback_show.id if obj.fallback_show else None,
default_pool="fallback" if obj.fallback_default_pool else "",
),
)
def get_playout(obj) -> RadioPlayoutSettings:
return RadioPlayoutSettings(
line_in_channels=obj.line_in_channels,
pools=obj.pools,
)
def get_station(obj) -> RadioStationSettings:
logo = (
Logo(
url=f"{settings.SITE_URL}{obj.station_logo.url}",
height=obj.station_logo.height,
width=obj.station_logo.width,
)
if obj.station_logo
else None
)
return RadioStationSettings(
name=obj.station_name,
logo=logo,
website=obj.station_website,
)

Ernesto Rico Schmidt
committed
# done this way to get the schema annotations for datetime right
class NestedTimeslotSerializer(serializers.Serializer):
end = serializers.DateTimeField()

Ernesto Rico Schmidt
committed
id = serializers.IntegerField(allow_null=True)
is_virtual = serializers.BooleanField()

Ernesto Rico Schmidt
committed
memo = serializers.CharField()
playlist_id = serializers.IntegerField(allow_null=True)
repetition_of_id = serializers.IntegerField(allow_null=True)
start = serializers.DateTimeField()

Ernesto Rico Schmidt
committed
class PlayoutEntrySerializer(serializers.Serializer):
episode = serializers.SerializerMethodField()
schedule = serializers.SerializerMethodField(allow_null=True)

Ernesto Rico Schmidt
committed
show = serializers.SerializerMethodField()
timeslot = NestedTimeslotSerializer()
@staticmethod
def get_episode(obj) -> NestedEpisode:
pass
@staticmethod
def get_schedule(obj) -> NestedSchedule:
pass
@staticmethod
def get_show(obj) -> NestedShow:
pass
class ProgramEntrySerializer(serializers.Serializer):
episode = serializers.SerializerMethodField()
show = serializers.SerializerMethodField()
timeslot = NestedTimeslotSerializer()
@staticmethod
def get_episode(obj) -> NestedEpisode:
pass
@staticmethod
def get_schedule(obj) -> NestedSchedule:
pass
@staticmethod
def get_show(obj) -> NestedShow:
pass