Per-field user overrides for auto-synced channels. Each nullable column represents a user-provided value that takes precedence over the matching field on the related Channel. Sync writes only to Channel.* fields and never to this table, so provider metadata keeps flowing while
| 980 | |
| 981 | |
| 982 | class ChannelOverride(models.Model): |
| 983 | """ |
| 984 | Per-field user overrides for auto-synced channels. |
| 985 | |
| 986 | Each nullable column represents a user-provided value that takes precedence |
| 987 | over the matching field on the related Channel. Sync writes only to |
| 988 | Channel.* fields and never to this table, so provider metadata keeps |
| 989 | flowing while user customizations persist across refreshes. Output |
| 990 | querysets resolve the effective value via |
| 991 | `apps.channels.managers.with_effective_values`. |
| 992 | """ |
| 993 | channel = models.OneToOneField( |
| 994 | Channel, |
| 995 | on_delete=models.CASCADE, |
| 996 | related_name="override", |
| 997 | ) |
| 998 | name = models.CharField(max_length=512, null=True, blank=True) |
| 999 | channel_number = models.FloatField(null=True, blank=True) |
| 1000 | channel_group = models.ForeignKey( |
| 1001 | ChannelGroup, |
| 1002 | on_delete=models.SET_NULL, |
| 1003 | null=True, |
| 1004 | blank=True, |
| 1005 | related_name="+", |
| 1006 | ) |
| 1007 | logo = models.ForeignKey( |
| 1008 | "Logo", |
| 1009 | on_delete=models.SET_NULL, |
| 1010 | null=True, |
| 1011 | blank=True, |
| 1012 | related_name="+", |
| 1013 | ) |
| 1014 | tvg_id = models.CharField(max_length=255, null=True, blank=True) |
| 1015 | tvc_guide_stationid = models.CharField(max_length=255, null=True, blank=True) |
| 1016 | epg_data = models.ForeignKey( |
| 1017 | EPGData, |
| 1018 | on_delete=models.SET_NULL, |
| 1019 | null=True, |
| 1020 | blank=True, |
| 1021 | related_name="+", |
| 1022 | ) |
| 1023 | stream_profile = models.ForeignKey( |
| 1024 | StreamProfile, |
| 1025 | on_delete=models.SET_NULL, |
| 1026 | null=True, |
| 1027 | blank=True, |
| 1028 | related_name="+", |
| 1029 | ) |
| 1030 | created_at = models.DateTimeField(auto_now_add=True) |
| 1031 | updated_at = models.DateTimeField(auto_now=True) |
| 1032 | |
| 1033 | def __str__(self): |
| 1034 | return f"Override for channel {self.channel_id}" |
| 1035 | |
| 1036 | def has_any_override(self) -> bool: |
| 1037 | return any( |
| 1038 | getattr(self, field) is not None |
| 1039 | for field in ( |