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.