Reorder a channel by moving it after another channel (or to the start if insert_after_id is null). Shifts other channels as needed to maintain contiguous ordering.
(self, request, pk=None)
| 2209 | ) |
| 2210 | @action(detail=True, methods=["post"], url_path="reorder") |
| 2211 | def reorder(self, request, pk=None): |
| 2212 | """ |
| 2213 | Reorder a channel by moving it after another channel (or to the start if insert_after_id is null). |
| 2214 | Shifts other channels as needed to maintain contiguous ordering. |
| 2215 | """ |
| 2216 | channel = self.get_object() |
| 2217 | insert_after_id = request.data.get("insert_after_id") |
| 2218 | old_channel_number = channel.channel_number |
| 2219 | |
| 2220 | with transaction.atomic(): |
| 2221 | if insert_after_id is None: |
| 2222 | # Move to the beginning (channel_number = 1) |
| 2223 | target_number = 0 |
| 2224 | desired_number = 1 |
| 2225 | else: |
| 2226 | try: |
| 2227 | target_channel = Channel.objects.get(id=insert_after_id) |
| 2228 | target_number = target_channel.channel_number or 0 |
| 2229 | desired_number = int(target_number) + 1 |
| 2230 | except Channel.DoesNotExist: |
| 2231 | return Response( |
| 2232 | {"error": "Target channel not found"}, |
| 2233 | status=status.HTTP_404_NOT_FOUND, |
| 2234 | ) |
| 2235 | |
| 2236 | if desired_number == old_channel_number: |
| 2237 | # No change needed |
| 2238 | return Response( |
| 2239 | { |
| 2240 | "message": f"Channel {channel.name} already at position {desired_number}", |
| 2241 | "channel": self.get_serializer(channel).data, |
| 2242 | }, |
| 2243 | status=status.HTTP_200_OK, |
| 2244 | ) |
| 2245 | |
| 2246 | if desired_number < old_channel_number: |
| 2247 | # Moving up: increment all channels between desired_number and old_channel_number-1 |
| 2248 | Channel.objects.filter( |
| 2249 | channel_number__gte=desired_number, |
| 2250 | channel_number__lt=old_channel_number |
| 2251 | ).update(channel_number=F('channel_number') + 1) |
| 2252 | channel.channel_number = desired_number |
| 2253 | channel.save(update_fields=['channel_number']) |
| 2254 | elif desired_number > old_channel_number: |
| 2255 | # Moving down: shift down channels between old+1 and desired-1, then set to desired-1 |
| 2256 | if desired_number > old_channel_number + 1: |
| 2257 | Channel.objects.filter( |
| 2258 | channel_number__gt=old_channel_number, |
| 2259 | channel_number__lt=desired_number |
| 2260 | ).update(channel_number=F('channel_number') - 1) |
| 2261 | channel.channel_number = desired_number - 1 |
| 2262 | channel.save(update_fields=['channel_number']) |
| 2263 | else: |
| 2264 | # No move or same position |
| 2265 | channel.channel_number = desired_number |
| 2266 | channel.save(update_fields=['channel_number']) |
| 2267 | |
| 2268 | return Response( |