Задать вопрос
  • Настройка админка Django: Как отобразить поля из одной модели на превью другой?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Django
    Седой и строгий
    Правильнее и проще было бы сделать UserInfoAdmin инлайном для UserAdmin. Но можно добиться и использования полей связанной модели:

    from six import with_metaclass
    from django.contrib import admin
    from django.db import models
    
    def getter_for_related_field(name, admin_order_field=None, short_description=None):
        related_names = name.split('__')
        def getter(self, obj):
            for related_name in related_names:
                obj = getattr(obj, related_name)
            return obj
        getter.admin_order_field = admin_order_field or name
        getter.short_description = short_description or related_names[-1].title().replace('_',' ')
        return getter
    
    
    class RelatedFieldAdminMetaclass(type(admin.ModelAdmin)):
        def __new__(cls, name, bases, attrs):
            new_class = super(RelatedFieldAdminMetaclass, cls).__new__(cls, name, bases, attrs)
            for field in new_class.list_display:
                if '__' in field:
                    setattr(new_class, field, getter_for_related_field(field))
            return new_class
    
    
    class RelatedFieldAdmin(with_metaclass(RelatedFieldAdminMetaclass, admin.ModelAdmin)):
        def get_queryset(self, request):
            qs = super(RelatedFieldAdmin, self).get_queryset(request)
            select_related = [field.rsplit('__',1)[0] for field in self.list_display if '__' in field]
            model = qs.model
            for field_name in self.list_display:
                try:
                    field = model._meta.get_field(field_name)
                except models.FieldDoesNotExist:
                    continue
                if isinstance(field.rel, models.ManyToOneRel):
                    select_related.append(field_name)
            return qs.select_related(*select_related)
    
    
    @admin.register(UserInfo)
    class UserInfoAdmin(RelatedFieldAdmin):
        list_display = ['user', 'user__first_name', 'user__last_name', 'user__email', 'position']
        list_display_links = list_display
        list_filter = ['user__is_staff', 'position']
        search_fields = ['user__username', 'user__first_name', 'user__last_name', 'user__email', 'position', 'phone', 'location']
    Ответ написан
    Комментировать