mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-17 16:50:53 +00:00
perf: eliminate three remaining N+1 queries in list endpoints
Layered on top of the prior perf commits, removes additional per-row queries Channel list (apps/channels): add auto_created_by to select_related so ChannelSerializer.get_auto_created_by_name does not fire one SELECT per row. Replace instance.streams.all().order_by(channelstream__order) in to_representation with a read off the prefetched channelstream_set. M3U account list (apps/m3u): prefetch_related "filters" on the viewset queryset and sort filters in Python over the prefetch in M3UAccountSerializer.get_filters. Frontend (EditableCell.jsx): align the saveValue useCallback dependency from [row.original.id] to [row.original] in the Number, Group, EPG, and Logo cells, matching the pattern applied to the Text cell.
This commit is contained in:
parent
ad83d968dc
commit
df7e6422df
5 changed files with 15 additions and 12 deletions
|
|
@ -852,6 +852,7 @@ class ChannelViewSet(viewsets.ModelViewSet):
|
|||
"epg_data",
|
||||
"stream_profile",
|
||||
"override",
|
||||
"auto_created_by",
|
||||
).prefetch_related(
|
||||
"streams",
|
||||
# Default-attr prefetch shares the cache with M2M writes;
|
||||
|
|
|
|||
|
|
@ -532,14 +532,14 @@ class ChannelSerializer(serializers.ModelSerializer):
|
|||
self.fields["streams"] = serializers.SerializerMethodField()
|
||||
return super().to_representation(instance)
|
||||
else:
|
||||
# Fix: For PATCH/PUT responses, ensure streams are ordered
|
||||
# Read from the prefetched channelstream_set (ordered by the
|
||||
# viewset's Prefetch); chaining .order_by() rebuilds the
|
||||
# queryset and fires one SELECT per row in list responses.
|
||||
representation = super().to_representation(instance)
|
||||
if "streams" in representation:
|
||||
representation["streams"] = list(
|
||||
instance.streams.all()
|
||||
.order_by("channelstream__order")
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
representation["streams"] = [
|
||||
cs.stream_id for cs in instance.channelstream_set.all()
|
||||
]
|
||||
return representation
|
||||
|
||||
def get_logo(self, obj):
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class M3UAccountViewSet(viewsets.ModelViewSet):
|
|||
|
||||
queryset = M3UAccount.objects.select_related(
|
||||
"refresh_task__crontab", "refresh_task__interval"
|
||||
).prefetch_related("channel_group", "profiles")
|
||||
).prefetch_related("channel_group", "profiles", "filters")
|
||||
serializer_class = M3UAccountSerializer
|
||||
|
||||
def get_permissions(self):
|
||||
|
|
|
|||
|
|
@ -370,7 +370,9 @@ class M3UAccountSerializer(serializers.ModelSerializer):
|
|||
return instance
|
||||
|
||||
def get_filters(self, obj):
|
||||
filters = obj.filters.order_by("order")
|
||||
# Sort over the prefetch cache; .order_by() would fire one SELECT
|
||||
# per account (viewset prefetches "filters").
|
||||
filters = sorted(obj.filters.all(), key=lambda f: f.order)
|
||||
return M3UFilterSerializer(filters, many=True).data
|
||||
|
||||
def get_earliest_expiration(self, obj):
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ const EditableNumberCellInner = ({ row, column, getValue, onBlur }) => {
|
|||
setValue(previousValue.current);
|
||||
}
|
||||
},
|
||||
[row.original.id, column.id, onBlur]
|
||||
[row.original, column.id, onBlur]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -434,7 +434,7 @@ const EditableGroupCellInner = ({
|
|||
notifyInlineSaveError(column.id, error);
|
||||
}
|
||||
},
|
||||
[row.original.id]
|
||||
[row.original]
|
||||
);
|
||||
|
||||
const handleChange = (newGroupId) => {
|
||||
|
|
@ -609,7 +609,7 @@ const EditableEPGCellInner = ({
|
|||
notifyInlineSaveError(column.id, error);
|
||||
}
|
||||
},
|
||||
[row.original.id]
|
||||
[row.original]
|
||||
);
|
||||
|
||||
const handleChange = (newEpgDataId) => {
|
||||
|
|
@ -779,7 +779,7 @@ const EditableLogoCellInner = ({ row, logoId, onBlur }) => {
|
|||
notifyInlineSaveError(column.id, error);
|
||||
}
|
||||
},
|
||||
[row.original.id]
|
||||
[row.original]
|
||||
);
|
||||
|
||||
const handleChange = (newLogoId) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue