2
votes

I can't figure out how to add the User full_name in the list_filter.

My Blog model is as follows:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone


class User(AbstractUser):
    pass

class Post(models.Model):
    POST_STATUS = (('borrador', 'Borrador'), ('publicado', 'Publicado'))

    title = models.CharField('titulo', max_length=100)
    body = models.TextField('cuerpo')
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts', verbose_name='autor')
    created = models.DateTimeField('creado', auto_now_add=True)
    published = models.DateTimeField('publicado', auto_now=True)
    updated = models.DateTimeField('actualizado', auto_now=True)
    slug = models.SlugField(max_length=100, unique_for_date='published')
    status = models.CharField(max_length=10, choices=POST_STATUS, default='borrador')

    class Meta:
        ordering = ('-published',)

    def __str__(self):
        return self.title

As you can see, I have created a custom user model just in case I have to change it in the future. In the Blog model, there is a 'author' field which uses the User as FK.

I want to add the posibility to filter by 'author' in the Blog's admin site. To do this I tried the following:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User, Post

admin.site.register(User, UserAdmin)

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'status', 'published')
    list_filter = ('author' , 'status', 'published')
    search_fields = [('title',), ('body',)]
    prepopulated_fields = {'slug': ('title',)}
    raw_id_fields = ('author',) # Reemplaza el drop-down para que parezca una lupa (para FKs)
    date_hierarchy = 'published'
    ordering = ('status', 'published')

The problem is that the filter by 'author' doesn't appear in the admin site: enter image description here

If I do this: list_filter = ('author__last_name' , 'status', 'published') the filter shows up, but it looks like this ('appellido' means last_name in Spanish:

enter image description here

I would like the filter's text to be 'por autor (by author)' and be able to filter by the author's full name.

Is that possible?

Thanks in advance!!

1

1 Answers

0
votes

Probably you can do that with django.contrib.admin.SimpleListFilter:

from datetime import date

from django.contrib import admin
from django.utils.translation import gettext_lazy as _

class PerAuthorListFilter(admin.SimpleListFilter):
    title = _('Per Author')
    parameter_name = 'per_author'

    def lookups(self, request, model_admin):
        authors = []
        for u in User.objects.all():
           authors.append((u.pk, '{} {}'.format(u.first_name, u.last_name)))

        return authors

    def queryset(self, request, queryset):
        queryset = super().queryset(request, queryset)
        return queryset.filter(author=self.value())

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_filter = [PerAuthorListFilter, ...]