list_filter optimization

if i had a class model that have hundreds of thousands of records inside my database and i’m using the django admin panel but i need to add a list filter inside the admin page to add this table to be filter by user where the user is a lender user but i do not need to retrieve all the table content inside the list filter because when i do it returns 504 because it loaded too much time and then it fails so what is your suggestion about this??
whenever adding the select_related it seems nothing changes and the same for list_select_related
serializers.py:

class WriteViewLogSerializer(serializers.ModelSerializer):
    """To Working With Create or Delete Action in ViewLogLoanRequest."""

    class Meta:
        model = ViewLogLoanRequest
        fields = ['loan_request', 'lender', 'date_time_of_view']
        validators = []

    def create(self, validated_data):
        instance, _ = ViewLogLoanRequest.objects.update_or_create(
            lender=validated_data['lender'], loan_request=validated_data['loan_request'],
            defaults={'date_time_of_view': validated_data['date_time_of_view']},
        )
        return instance

viewsets.py:

class ViewLogLoanReqestViewSet(mixins.DestroyModelMixin, mixins.ListModelMixin, mixins.CreateModelMixin, GenericViewSet):
    permission_classes = [IsLender]
    serializer_class = serializers.WriteViewLogSerializer

    def create(self, request, *args, **kwargs):
        user = self.request.user
        if 'loan_request' not in self.request.data:
            logger.warning('No Loan Request ID given')
            return Response(status=status.HTTP_204_NO_CONTENT)
        datetimeNow = timezone.now()
        data = {
            'lender': user.id,
            'loan_request': request.data['loan_request'],
            'date_time_of_view': datetimeNow.strftime("%Y-%m-%d %H:%M:%S")
        }
        serializer = self.get_serializer(data=data)
        if serializer.is_valid():
            try:
                loan_req = LoanRequest.objects.get(pk=request.data['loan_request'])
                loan_req.count_views += 1
                loan_req.save()
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            except LoanRequest.DoesNotExist:
                logger.warning('No Loan Request with given ID', extra={'loan_request': request.data['loan_request']})
                return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            logger.warning('Error getting Loan Request', extra={'loan_request': request.data['loan_request']})
            return Response(status=status.HTTP_204_NO_CONTENT)

    @action(detail=True, methods=['get'])
    def num_views(self, request, *args, **kwargs):
        loan_request_id = kwargs['pk']
        num_views = ViewLogLoanRequest.objects.filter(loan_request=loan_request_id).count()
        return Response({'num_views': num_views}, status=status.HTTP_200_OK)

    def get_queryset(self):
        if getattr(self, 'swagger_fake_view', False):
            # Return an empty queryset for schema generation metadata
            return ViewLogLoanRequest.objects.none()

admin.py:

class ViewLogLoanRequestAdmin(admin.ModelAdmin):
    list_display = ['id', 'lender', 'loan_request', 'date_time_of_view', 'created']
    search_fields = ['loan_request__borrower__email', 'id', 'lender__email']
    list_filter = ['date_time_of_view', 'created', 'lender', 'borrower']

models.py:

class ViewLogLoanRequest(TimeStampedModel):
    """Store LoanRequest that are viwed by Lender."""

    lender = models.ForeignKey(User, related_name='user_view_log_loan_request', on_delete=models.CASCADE)
    loan_request = models.ForeignKey(LoanRequest, related_name='loan_view_log_loan_request', on_delete=models.CASCADE)
    date_time_of_view = models.DateTimeField()

    def __str__(self):
        return "{} has viewed {}".format(self.lender.get_full_name(), self.loan_request.id)

    class Meta:
        ordering = ['id']
        unique_together = ['lender', 'loan_request']

1 Like

You have a couple different options depending upon the exact UX/UI you wish to provide.

First, if you know that the list you want to filter by is a smaller, more manageable set, you could create a custom list filter to only identify the entries you want included.

If that’s still too many entries, you could implement a text box as the filter field to enter the name to filter on. See the thread (and the referenced link) at foreign key daterange filtering in admin. The thread’s not an exact match, but the link in my response should be close to what you may want.

1 Like

Thank you for your suggestions.
it was solved by creating a custom list filters.