Prefetch only one/latest object in Django

Viewed 661

serialzer

class DriverSerializer(QueryFieldsMixin, serializers.ModelSerializer):
    notes = DriverNoteSerializer(many=True, read_only=True)
    rentals = DriverRentalSerializer(many=True, read_only=True)
    latest_returned_rentals = DriverRentalSerializer(read_only=True)

    class Meta:
        model = Driver
        fields = '__all__'

    @staticmethod
    def setup_eager_loading(queryset):
        """ Perform necessary eager loading of data. """
        # Prefetch for subsets of relationships
        # latest_returned_rental =
        queryset = queryset.prefetch_related(
            Prefetch('drivernote_set',
                     queryset=DriverNote.objects.filter(driver_id__in=queryset).order_by('-date_created')
                     .select_related('owner'), to_attr='notes'),
            Prefetch('rental_set',
                     queryset=Rental.objects.filter(state__in=['active', 'reserved'], driver_id__in=queryset).select_related('vehicle').select_related('driver'), to_attr='rentals'),
            Prefetch('rental_set',
                     queryset=Rental.objects.filter(state='returned', driver_id__in=queryset).select_related('vehicle').select_related(
                         'driver')[0], to_attr='latest_returned_rentals')
        )
        return queryset

view

class DriverListView(LoggingMixin, ListCreateAPIView):
    """
    get:
    Return a list of all the existing drivers.

    post:
    Create a new driver instance.
    """

    logging_methods = ['POST']
    serializer_class = DriverSerializer
    filter_backends = (OrderingFilter, SearchFilter, DjangoFilterBackend)
    # filter_fields = ('driver_state', 'first_name', 'last_name')
    filter_class = DriverFieldsFilter
    # Add others once discussed
    search_fields = ('first_name', 'last_name', )
    ordering_fields = '__all__'

Relevant logs:

 File "C:\Users\Borko\envs\sally-env\lib\site-packages\rest_framework\mixins.py", line 40, in list
    queryset = self.filter_queryset(self.get_queryset())
  File "C:\Users\Borko\PycharmProjects\ops4\drivers\views.py", line 40, in get_queryset
    queryset = self.get_serializer_class().setup_eager_loading(queryset)
  File "C:\Users\Borko\PycharmProjects\ops4\drivers\serializers.py", line 49, in setup_eager_loading
'driver')[0], to_attr='latest_returned_rentals')

AttributeError at /api/drivers/
'Rental' object has no attribute '_iterable_class'

Is there any way to grab just the latest object via Prefetch? Let's say I'm trying to pull in all active and reserved rentals, but I only want to pull one rental with state returned (latest)? How would I go about accomplishing that?

EDIT: For anyone that cares - I solved this by using SerializerMethodField and sorting through the prefetched query (via attribute rentals) there via python to avoid additional DB hits. Unfortunately prefetch accepts only a queryset not an item.

0 Answers
Related