Django 1.4 User Admin list_filter using UserProfile field
Asked Answered
B

1

4

EDIT: I updated the code to reflect one mistake in the queryset filter, where I had user__user_type, has been replaced with the correct userprofile__user_type.

I'm using Django 1.4, and I understand there's a new feature to create custom list_filters for the admin, that replaced the FilterSpec API.

I've read countless SO posts about creating custom admin list_filters, but I'm still stuck.

My use case is for a list_filter for my User objects that's referencing a field in the UserProfile Model.

So in models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    user_type = models.CharField(max_length=25, choices=USER_TYPES, default='Client')
    ...

and in admin.py:

from django.contrib import admin
from django.contrib.admin import site, ModelAdmin, ChoicesFieldListFilter
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from models import UserProfile

class UserTypeFilter(ChoicesFieldListFilter):
    title = 'User Type'
    parameter_name = 'user_type'

    def lookups(self, request, model_admin):
        usertypes = set([c.user_type for c in UserProfile.objects.all()])
        return [(c.id, c.user_type) for c in usertypes]

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(userprofile__user_type=self.value())
        else:
            return queryset

class UserAdmin(UserAdmin):
    list_filter = ('is_staff', UserTypeFilter)
    inlines = (UserProfileInline, )


admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Here's the error I get:

'UserAdmin.list_filter[1]' is 'UserTypeFilter' which is of type FieldListFilter but is not associated with a field name.

I originally tried using the SimpleListFilter, and got this error

'unicode' object has no attribute 'id'

Which makes sense, because my user_type field is a choice field, and the choices are unicode objects.

The docs show this example:

class PersonAdmin(UserAdmin):
    list_filter = ('company__name',)

But this seems to imply that 'company' is a field on the User model. Do I need to redefine my User model to include a OneToOneField for UserProfile? Or am I missing some obvious way to reference a user's profile?

Thanks,

Bondon answered 4/10, 2013 at 17:10 Comment(0)
S
3

The first error you reference seems to be specific to FieldListFilter which I've never used. I guess the point of it is to automate something related to a specific field.

I see no use for it with your example as you're supplying all options.

I'd just use a SimpleListFilter for now...

Anyways your error is that usertypes is a set of c.user_type which is a string. It has no id attribute.

You need to return [(c, c) for c in usertypes] where the first value is the value passed to your QS, and the second is the display value.

The rest doesn't need to change.

Snowblink answered 4/10, 2013 at 17:24 Comment(2)
I know this space is not supposed to be for saying "thanks," but your answer was so fast and so spot-on, that I'm doing it anyway. You rock. Thanks.Bondon
@AnthonyRoberts, no problem man! The question was clear / the model snippet was key.Dimitry

© 2022 - 2024 — McMap. All rights reserved.