【问题标题】:Admin: Show related inline ManyToMany objects as MultipleChoiceField管理员:将相关的内联 ManyToMany 对象显示为 MultipleChoiceField
【发布时间】:2021-04-16 13:27:59
【问题描述】:

我已经覆盖了 UserAdmin 类,并希望将用户配置文件和一些相关对象添加为内联对象。

Userprofile 按预期工作,但对于 ManyToMany 关系,我现在得到一个包含相关对象的表。这对我的应用程序来说并不是很理想,更改相关对象有点麻烦,并且不需要这种方式添加新对象。

我想要一个包含相关对象的简单 MultipleChoiceField。有没有简单的方法来实现这一点?

这是我的用户资料/admin.py:

from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from django_admin_listfilter_dropdown.filters import RelatedOnlyDropdownFilter

from driverslog.models import Branch
from driverslog.models import Car
from .models import Userprofile

User = get_user_model()


class ProfileInline(admin.TabularInline):
    model = Userprofile
    can_delete = False
    max_num = 0
    extra = 0
    fk_name = 'user'


class CarInline(admin.TabularInline):
    model = Car.users.through
    can_delete = True
    verbose_name = _('Car')
    verbose_name_plural = _('Cars')
    extra = 0


class BranchInline(admin.TabularInline):
    model = Branch.users.through
    can_delete = True
    verbose_name = _('Branch')
    verbose_name_plural = _('Branches')
    extra = 0


class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, BranchInline, CarInline)
    list_display = ('username', 'first_name', 'last_name', 'is_staff', 'is_superuser', 'represents')
    list_filter = ('is_active', 'is_staff', 'is_superuser', ('groups', RelatedOnlyDropdownFilter),
                   ('branches', RelatedOnlyDropdownFilter), ('profile__represent', RelatedOnlyDropdownFilter),
                   ('car', RelatedOnlyDropdownFilter))

    def represents(self, obj):
        return obj.profile.represent.count()

    represents.short_description = _('Represents')

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

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    我现在不使用内联字段就解决了。

    我所做的是覆盖 UserChangeForm 并添加反向关系的字段。它按预期工作,到目前为止我没有发现任何缺点(直到现在......)。

    admin.py:

    class CustomUserAdmin(UserAdmin):
        inlines = (ProfileInline,)
        form = UserForm
        ...
        fieldsets = (
            (_('Personal info'), {'fields': ('username', 'first_name', 'last_name', 'email')}),
            (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
            (_('Assignments'), {'fields': ('branches', 'cars')}),
        )
    

    forms.py:

    class UserForm(UserChangeForm):
        branches = forms.ModelMultipleChoiceField(queryset=Branch.objects.all())
        cars = forms.ModelMultipleChoiceField(queryset=Car.objects.all())
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            instance = kwargs.get('instance')
            if instance:
                self.fields["branches"].initial = instance.branches.all().values_list('id', flat=True)
                self.fields["cars"].initial = instance.cars.all().values_list('id', flat=True)
    
        def save(self, commit=True):
            if self.is_valid():
                self.instance.cars.set(self.cleaned_data.get('cars'))
                self.instance.branches.set(self.cleaned_data.get('branches'))
            return super().save(commit)
    
    

    models.py:

    class Userprofile(models.Model):
        class Meta:
            verbose_name = _('Profile')
            verbose_name_plural = _('Profiles')
        user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, unique=True, related_name='profile', verbose_name=_('User'))
        represent = models.ManyToManyField(get_user_model(), related_name='represent', blank=True, verbose_name=_('Represents'))
    

    【讨论】:

      【解决方案2】:

      2017年后,django新增filter_horizontal属性。

      class CustomUserAdmin(UserAdmin):
          filter_horizontal = ('branches', 'cars')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-10
        • 2019-04-14
        • 2019-05-10
        • 1970-01-01
        相关资源
        最近更新 更多