Troy
Troy

Reputation: 21902

In the Django admin, how can I filter down the options Django displays for a ManyToManyField that is part of the `fieldsets` property?

Say I have models that looks like this:

class MyOtherModel(model.Model):
    name = CharField(max_length=50)
    type = CharField(max_length=5, default='A')

class MyModel(models.Model):
    name = CharField(max_length=50)
    some_m2m = ManyToManyField('MyOtherModel')

and, in the admin, I want it to split up the MyOtherModel instances, based on type, to display in different parts of the screen, or with a different label, or whatever.

I'd like to be able to do something like this (like you can do with the list_display property of a ModelAdmin):

class MyModelAdmin(admin.ModelAdmin):
    model = MyModel
    fieldsets = [
        (None, {
            'fields': [
                ('name', 'some_m2m_type_A', 'some_m2m_type_B',)
            ]
        })
    ]

    def some_m2m_type_A(self):
        return MyOtherModel.objects.filter(type='A')

    def some_m2m_type_B(self):
        return MyOtherModel.objects.filter(type='B')

which, obviously, won't work, but you get the idea.


I tried overriding formfield_for_manytomany():

def formfield_for_manytomany(self, db_field, request=None, **kwargs):
    if db_field == 'some_m2m_type_A':
        kwargs["queryset"] = MyOtherModel.objects.filter(type='A')
    elif db_field == 'some_m2m_type_B':
        kwargs["queryset"] = MyOtherModel.objects.filter(type='B')
    return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

similar to what is suggested in this question, but Django still errors out with:

FieldError: Unknown field(s) (some_m2m_type_A, some_m2m_type_B) specified for MyModel. Check fields/fieldsets/exclude attributes of class MyModelAdmin.

and it errors out BEFORE it ever calls formfield_for_manytomany()...

Is there a simple way to accomplish what I'm after in the Django Admin? Or is it going to require a huge overhaul, overriding templates, and other hard-to-maintain hackery?

Upvotes: 1

Views: 599

Answers (1)

markwalker_
markwalker_

Reputation: 12869

You could define your own through model;

class MyOtherModel(model.Model):
    name = CharField(max_length=50)
    type = CharField(max_length=5, default='A')

class MyModel(models.Model):
    name = CharField(max_length=50)
    some_m2m = ManyToManyField('MyOtherModel', through='MyThroughModel')

class MyThroughModel(models.Model):
    mymodel = models.ForeignKey(MyModel)
    myothermodel = models.ForeignKey(MyOtherModel)

Then in admin.py;

class MyOtherModelAdmin(admin.ModelAdmin):
    model = MyOtherModel
    list_filter = ['mythroughmodel_set__myothermodel__type']

Upvotes: 0

Related Questions