Django filters - Using an AllValuesFilter (with a LinkWidget) on a ManyToManyField

Posted by magnetix on Stack Overflow See other posts from Stack Overflow or by magnetix
Published on 2010-01-23T07:09:11Z Indexed on 2010/03/13 12:05 UTC
Read the original article Hit count: 236

Filed under:
|

This is my first Stack Overflow question, so please let me know if I do anything wrong.

I wish to create an AllValues filter on a ManyToMany field using the wonderful django-filters application. Basically, I want to create a filter that looks like it does in the Admin, so I also want to use the LinkWidget too.

Unfortunately, I get an error (Invalid field name: 'operator') if I try this the standard way:

# Models
class Organisation(models.Model):
    name = models.CharField()  
    ...  

class Sign(models.Model):  
    name = models.CharField()  
    operator = models.ManyToManyField('Organisation', blank=True)  
    ...  

# Filter
class SignFilter(LinkOrderFilterSet):  
    operator = django_filters.AllValuesFilter(widget=django_filters.widgets.LinkWidget)  

    class Meta:
        model = Sign
        fields = ['operator']

I got around this by creating my own filter with the many to many relationship hard coded:

# Models
class Organisation(models.Model):
    name = models.CharField()  
    ...  

class Sign(models.Model):  
    name = models.CharField()  
    operator = models.ManyToManyField('Organisation', blank=True)  
    ...  

# Filter
class MyFilter(django_filters.ChoiceFilter):  
    @property  
    def field(self):  
        cd = {}  
        for row in self.model.objects.all():  
            orgs = row.operator.select_related().values()  
        for org in orgs:  
            cd[org['id']] = org['name']    
        choices = zip(cd.keys(), cd.values())  
        list.sort(choices, key=lambda x:(x[1], x[0]))  
        self.extra['choices'] = choices  
        return super(AllValuesFilter, self).field  

class SignFilter(LinkOrderFilterSet):  
    operator = MyFilter(widget=django_filters.widgets.LinkWidget)  

I am new to Python and Django. Can someone think of a more generic/elegant way of doing this?

© Stack Overflow or respective owner

Related posts about django

Related posts about django-filter