Filter ManyToMany box in Django Admin Filter ManyToMany box in Django Admin django django

Filter ManyToMany box in Django Admin


Ok, this is my solution using above classes.I added a bunch more filters to filter it correctly, but I wanted to make the code readable here.

This is exactly what I was looking for, and I found my solution here: http://www.slideshare.net/lincolnloop/customizing-the-django-admin#stats-bottom (slide 50)

Add the following to my admin.py:

class CustomerForm(forms.ModelForm):     def __init__(self, *args, **kwargs):        super(CustomerForm, self).__init__(*args, **kwargs)        wtf = Category.objects.filter(pk=self.instance.cat_id);        w = self.fields['categories'].widget        choices = []        for choice in wtf:            choices.append((choice.id, choice.name))        w.choices = choicesclass CustomerAdmin(admin.ModelAdmin):    list_per_page = 100    ordering = ['submit_date',] # didnt have this one in the example, sorry    search_fields = ['name', 'city',]    filter_horizontal = ('categories',)    form = CustomerForm

This filters the "categories" list without removing any functionality! (ie: i can still have my beloved filter_horizontal :))

The ModelForms is very powerful, I'm a bit surprised it's not covered more in the documentation/book.


As far as i can understand you, is that you basically want to filter the shown choices according to some criteria (category according to city).

You can do exactly that by using limit_choices_to attribute of models.ManyToManyField. So changing your model definition as...

class Customer(models.Model):    name = models.CharField(max_length=200)    city = models.ForeignKey(City)    categories = models.ManyToManyField(Category, limit_choices_to = {'available_in': cityId})

This should work, as limit_choices_to, is available for this very purpose.

But one things to note, limit_choices_to has no effect when used on a ManyToManyField with a custom intermediate table. Hope this helps.


Another way is with formfield_for_manytomany in Django Admin.

class MyModelAdmin(admin.ModelAdmin):    def formfield_for_manytomany(self, db_field, request, **kwargs):        if db_field.name == "cars":            kwargs["queryset"] = Car.objects.filter(owner=request.user)        return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

Considering that "cars" are the ManyToMany field.

Check this link for more info.