(self, instance, validated_data)
| 245 | return data |
| 246 | |
| 247 | def update(self, instance, validated_data): |
| 248 | # Pop exp_date — it's written to the default profile, not the account |
| 249 | exp_date = validated_data.pop("exp_date", "__NOT_SET__") |
| 250 | |
| 251 | # Pop cron_expression before it reaches model fields |
| 252 | # If not present (partial update), preserve the existing cron from the PeriodicTask |
| 253 | if "cron_expression" in validated_data: |
| 254 | cron_expr = validated_data.pop("cron_expression") |
| 255 | else: |
| 256 | cron_expr = "" |
| 257 | if instance.refresh_task_id and instance.refresh_task and instance.refresh_task.crontab: |
| 258 | ct = instance.refresh_task.crontab |
| 259 | cron_expr = f"{ct.minute} {ct.hour} {ct.day_of_month} {ct.month_of_year} {ct.day_of_week}" |
| 260 | instance._cron_expression = cron_expr |
| 261 | |
| 262 | # Handle enable_vod preference and auto_enable_new_groups settings |
| 263 | enable_vod = validated_data.pop("enable_vod", None) |
| 264 | auto_enable_new_groups_live = validated_data.pop("auto_enable_new_groups_live", None) |
| 265 | auto_enable_new_groups_vod = validated_data.pop("auto_enable_new_groups_vod", None) |
| 266 | auto_enable_new_groups_series = validated_data.pop("auto_enable_new_groups_series", None) |
| 267 | |
| 268 | # Merge client-supplied custom_properties over the existing blob |
| 269 | # so unrelated keys persist. The dedicated preference fields below |
| 270 | # overwrite their corresponding keys; clients should set those via |
| 271 | # the typed top-level fields rather than the custom_properties |
| 272 | # payload. |
| 273 | incoming_custom = {} |
| 274 | if "custom_properties" in validated_data: |
| 275 | incoming_custom = validated_data["custom_properties"] or {} |
| 276 | if not isinstance(incoming_custom, dict): |
| 277 | incoming_custom = ensure_custom_properties_dict(incoming_custom) |
| 278 | existing_custom = instance.custom_properties or {} |
| 279 | if not isinstance(existing_custom, dict): |
| 280 | existing_custom = ensure_custom_properties_dict(existing_custom) |
| 281 | custom_props = {**existing_custom, **incoming_custom} |
| 282 | |
| 283 | if enable_vod is not None: |
| 284 | custom_props["enable_vod"] = enable_vod |
| 285 | if auto_enable_new_groups_live is not None: |
| 286 | custom_props["auto_enable_new_groups_live"] = auto_enable_new_groups_live |
| 287 | if auto_enable_new_groups_vod is not None: |
| 288 | custom_props["auto_enable_new_groups_vod"] = auto_enable_new_groups_vod |
| 289 | if auto_enable_new_groups_series is not None: |
| 290 | custom_props["auto_enable_new_groups_series"] = auto_enable_new_groups_series |
| 291 | |
| 292 | validated_data["custom_properties"] = custom_props |
| 293 | |
| 294 | # Pop out channel group memberships so we can handle them manually |
| 295 | channel_group_data = validated_data.pop("channel_group", []) |
| 296 | |
| 297 | # First, update the M3UAccount itself |
| 298 | for attr, value in validated_data.items(): |
| 299 | setattr(instance, attr, value) |
| 300 | instance.save() |
| 301 | |
| 302 | # Prepare a list of memberships to update |
| 303 | memberships_to_update = [] |
| 304 | for group_data in channel_group_data: |
no test coverage detected