BlogVenv\Lib\site-packages\django\contrib\auth\admin.py

from allauth.socialaccount.models import SocialAccount    # 추가
...

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    add_form_template = 'admin/auth/user/add_form.html'
    change_user_password_template = None
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'getSocialAccount')    # getSocialAccount 추가
    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('groups', 'user_permissions',)

    # 추가
    def getSocialAccount(self, user):
        try:
            sa = SocialAccount.objects.get(user=user)
        except SocialAccount.DoesNotExist as e:
            sa = None
            
        return sa.provider if sa else ""

    getSocialAccount.short_description = "Social Account"

...

각 User별로 건건이 Query한다. 비효율적이다.
admin mode에서 queryset을 join문으로 override하는 방법 찾아봐야한다.

 

개선된 소스

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    add_form_template = 'admin/auth/user/add_form.html'
    change_user_password_template = None
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'getSocialAccount')
    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('groups', 'user_permissions',)

    '''
    https://docs.djangoproject.com/en/3.0/ref/models/querysets/#filteredrelation-object
    get_queryset method를 override하여 left outer join을 한다. 
    그리고 list_display에서 바로 queryset에서 지정한 provider alias를 바로 호출할 수는 없기때문에 기존처럼 getSocialAccount를 통하여 조회한다.
    '''
    def get_queryset(self, request):
        qs = admin.ModelAdmin.get_queryset(self, request)
        qs = qs.annotate(SocalAccount=FilteredRelation("socialaccount"))
        qs = qs.annotate(provider=F("socialaccount__provider"))
        return qs

    def getSocialAccount(self, user):
        return user.provider

    getSocialAccount.short_description = "Social Account"

 

User가 속한 Group도 표시해보자. (최종버전)
prefetch_related를 활용하여 -> http://blog.daonelab.com/post/12/1653/

from django.conf import settings
from django.contrib import admin, messages
from django.contrib.admin.options import IS_POPUP_VAR
from django.contrib.admin.utils import unquote
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import (
    AdminPasswordChangeForm, UserChangeForm, UserCreationForm,
)
from django.contrib.auth.models import Group, User
from django.core.exceptions import PermissionDenied
from django.db import router, transaction
from django.db.models import F, FilteredRelation    # 추가
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import path, reverse
from django.utils.decorators import method_decorator
from django.utils.html import escape
from django.utils.translation import gettext, gettext_lazy as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters

...

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    add_form_template = 'admin/auth/user/add_form.html'
    change_user_password_template = None
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_active', 'is_staff', 'is_superuser', 'getSocialAccount', 'getGroups')
    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('groups', 'user_permissions',)

    '''
    https://docs.djangoproject.com/en/3.0/ref/models/querysets/#filteredrelation-object
    https://docs.djangoproject.com/en/3.0/ref/models/querysets/#prefetch-related

    Override the get_queryset method to perform a left outer join.
    Also, provider alias specified in queryset cannot be called directly in list_display, 
    so retrieve through getSocialAccount as before.
    '''
    def get_queryset(self, request):
        qs = admin.ModelAdmin.get_queryset(self, request)
        qs = qs.annotate(SocalAccount=FilteredRelation("socialaccount"))
        qs = qs.annotate(provider=F("socialaccount__provider"))
        qs = qs.prefetch_related("groups")
        return qs

    def getSocialAccount(self, user):
        return user.provider

    getSocialAccount.short_description = "Social Account"

    def getGroups(self, user):
        return ", ".join(group.name for group in user.groups.all())
    
    getGroups.short_description = "Groups"

...

um.. 완벽해