Opened 10 days ago

Last modified 4 days ago

#28897 new Bug

FieldError when performing custom action in Admin Interface IF data is sorted by an annotated field

Reported by: Colton Hicks Owned by: nobody
Component: contrib.admin Version: 2.0
Severity: Normal Keywords: Admin Interface, Custom Action, Annotated Field,
Cc: Sergey Fedoseev Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

A FieldError results if I try to perform a custom a custom action on data in the admin interface IF that data is sorted by an annotated field. The action is obviously not acting on an annotated field as those fields do not exist in the database, but raises a FieldError saying it 'Cannot resolve keyword 'field_that_data_is_currently_sorted_by' into field.' and then lists the choices for fields (all of which are the raw model fields, not the annotated fields in the custom queryset).

My admin model:

@admin.register(Position)
class PositionAdmin(admin.ModelAdmin):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def get_queryset(self, request):

        qs = super(PositionAdmin, self).get_queryset(request).prefetch_related(
            'orders').select_related(
                'portfolio', 'current_position').select_related(
                    'current_position').annotate(
                Count('orders', distinct=True),
                Count('short_requests'),
                total_position_value=ExpressionWrapper(
                    F('price') * F('quantity'), output_field=IntegerField()),
                diff_shares=Coalesce(
                    F('quantity')
                    - F('current_position__quantity'),
                    F('quantity')),
                diff_value=ExpressionWrapper(
                    F('diff_shares') * F('price'),
                    output_field=IntegerField()),
                orders_with_errors=Count(
                    Case(When(~Q(orders__error=''), then=1))),
                non_accepted_orders=Count(
                    Case(When(Q(orders__status=''), then=1))),
                order_today=Count(
                    Case(When(
                        orders__created_at__gte=_brokerage_today_start(),
                        then=1))))
        return qs

    # Custom Action
    def approve_position_for_trading(self, request, queryset):
        try:
            num_pos_approved = queryset.update(approved=True)
        except FieldError:
            self.message_user(
                request, "You cannot perform actions when you have sorted by "
                "this column. Please remove your column sortings and then try "
                "your action again.", level=messages.ERROR)
        else:
            if num_pos_approved == 1:
                message_bit = "1 position was was"
            else:
                message_bit = "%s positions were" % num_pos_approved
            self.message_user(
                request, "%s successfully approved for trading." % message_bit)

I had to write code to handle the error so that the user will know how to proceed. However, this seems like bad behavior. Django can successfully perform that action (changing the 'Approved' field to 'True') on the data if it is sorted by any core model field, or if sorted by no field at all. However, if the data is sorted by a field resulting from the annotation of my queryset, then I get the FieldError when I try to perform the action. This seems like a bug.

Change History (2)

comment:1 Changed 4 days ago by Sergey Fedoseev

Could you provide traceback and try minimize your example?

comment:2 Changed 4 days ago by Sergey Fedoseev

Cc: Sergey Fedoseev added
Note: See TracTickets for help on using tickets.
Back to Top