0

So i have this simplified version of what i'm attempting to do and failing. I have this Boxes objects that has a color field, and can have many items by an m2m field, so i want a list(a queryset) of all the items that are in boxes of an specific color. So i made this django filter for the admin.

from django.contrib.admin import SimpleListFilter
from store.models import Box

class Items(Model):
    name = CharField(max_length=200)

class Box(Model):
    items = ManyToManyField(Items)
    color_choices = (
        ('yellow','yellow'),
        ('green','green'),
    )
    box_color = CharField(max_length=200,choices=color_choices)

# So in my Items admin list i want to filter the items by color, this is my 'failed' attemp.

class Items_by_payment_system_filter(SimpleListFilter):
    title = _('Colors')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'color'

    def lookups(self, request, model_admin):
        """
        Returns a list of tuples. The first element in each
        tuple is the coded value for the option that will
        appear in the URL query. The second element is the
        human-readable name for the option that will appear
        in the right sidebar.
        """
        return Box.color_choices
    def queryset(self, request, queryset):
        # Remember that self.value contains the current selection in the filter options displayed to the user in Admin
        if self.values():
            boxes = Box.objects.filter(items__in=queryset) # get only boxes with the current set of items
            boxes_ids = boxes.filter(box_color=self.values()).values_list('items__id',flat=True)
            return queryset.filter(id__in=boxes_ids)

I'm not sure what is wrong, because the admin is showing me items that belong to boxes with different colors other than the one i chose.

Guillermo Siliceo Trueba
  • 4,251
  • 5
  • 34
  • 47

1 Answers1

1

This is your problem :

  • change self.values to self.value in if self.values():
  • change color to box_color in boxes_ids = boxes.filter(color=self.values()) ...

Code Example (Test and work on django 1.4.2)

from box.models import Items,Box
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import SimpleListFilter

class Items_by_payment_system_filter(SimpleListFilter):
    title = _('Colors')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'color'

    def lookups(self, request, model_admin):
        """
        Returns a list of tuples. The first element in each
        tuple is the coded value for the option that will
        appear in the URL query. The second element is the
        human-readable name for the option that will appear
        in the right sidebar.
        """
        return Box.color_choices
    def queryset(self, request, queryset):
        # Remember that self.value contains the current selection in the filter options displayed to the user in Admin

        if self.value():
            boxes = Box.objects.filter(items__in=queryset) # get only boxes with the current set of items
            boxes_ids = boxes.filter(box_color=self.value()).values_list('items__id',flat=True)
            return queryset.filter(id__in=boxes_ids)


class ItemsAdmin(admin.ModelAdmin):
    fields = ['name']
    list_filter = (Items_by_payment_system_filter,)

admin.site.register(Items,ItemsAdmin)
admin.site.register(Box)
Pattapong J
  • 1,204
  • 12
  • 21