Assign User-objects to a Group while editing Group-object in Django admin

后端 未结 4 967
鱼传尺愫
鱼传尺愫 2021-01-12 08:56

In the default Django admin view for user-object (edit user) one can edit the user\'s group memberships. What if I wanted this the other way around also? I.e. in the group e

相关标签:
4条回答
  • 2021-01-12 08:59

    The save method above won't work if you add a new group and simultaneously add users to the group. The problem is that the new group won't get saved (the admin uses commit=False) and won't have a primary key. Since the purpose of save_m2m() is to allow the calling view to handle saving m2m objects, I made a save object that wraps the old save_m2m method in a new method.

    def save(self, commit=True):
        group = super(GroupAdminForm, self).save(commit=commit)
    
        if commit:
            group.user_set = self.cleaned_data['users']
        else:
            old_save_m2m = self.save_m2m
            def new_save_m2m():
                old_save_m2m()
                group.user_set = self.cleaned_data['users']
            self.save_m2m = new_save_m2m
        return group
    
    0 讨论(0)
  • 2021-01-12 09:06

    Here is a simpler approach that uses Django's InlineModelAdmin objects (answered here on Qubanshi.cc)

    from django.contrib.auth.admin import GroupAdmin
    from django.contrib.auth.models import User, Group
    
    class UserSetInline(admin.TabularInline):
        model = User.groups.through
        raw_id_fields = ('user',)  # optional, if you have too many users
    
    class MyGroupAdmin(GroupAdmin):
        inlines = [UserSetInline]
    
    # unregister and register again
    admin.site.unregister(Group)
    admin.site.register(Group, MyGroupAdmin)
    
    0 讨论(0)
  • 2021-01-12 09:12

    yourapp/admin.py

    from django import forms
    from django.contrib import admin
    from django.utils.translation import ugettext_lazy as _
    from django.contrib.admin.widgets import FilteredSelectMultiple
    
    from django.contrib.auth.models import User, Group
    
    class GroupAdminForm(forms.ModelForm):
        users = forms.ModelMultipleChoiceField(
            queryset=User.objects.all(), 
            required=False,
            widget=FilteredSelectMultiple(
                verbose_name=_('Users'),
                is_stacked=False
            )
        )
    
        class Meta:
            model = Group
    
        def __init__(self, *args, **kwargs):
            super(GroupAdminForm, self).__init__(*args, **kwargs)
    
            if self.instance and self.instance.pk:
                self.fields['users'].initial = self.instance.users.all()
    
        def save(self, commit=True):
            group = super(GroupAdminForm, self).save(commit=False)
    
            if commit:
                group.save()
    
            if group.pk:
                group.users = self.cleaned_data['users']
                self.save_m2m()
    
            return group
    
    class GroupAdmin(admin.ModelAdmin):
        form = GroupAdminForm
    
    admin.site.unregister(Group)
    admin.site.register(Group, GroupAdmin)
    
    0 讨论(0)
  • 2021-01-12 09:19

    I am on Django 2.1 and was using the solution posted by Chris, but like explained by Cedric, it wouldn't work when when a new group was added and simultaneously users were added to the new group. Unfortunately, his code didn't help either, but I could get it to work using this modified version below.

    Edit: I included the suggestion of user am70 (thanks!) and made use of get_user_model(). This code continues to work with Django 3.1 and has been tested with Python 3.6, 3.7 and 3.8.

    from django import forms
    from django.contrib import admin
    from django.utils.translation import ugettext_lazy as _
    from django.contrib.admin.widgets import FilteredSelectMultiple
    from django.contrib.auth import get_user_model ; User = get_user_model()
    from django.contrib.auth.models import Group
    
    class GroupAdminForm(forms.ModelForm):
        users = forms.ModelMultipleChoiceField(
            queryset=User.objects.all(), 
            required=False,
            widget=FilteredSelectMultiple(
                verbose_name=_('Users'),
                is_stacked=False
            )
        )
    
        class Meta:
            model = Group
    
        def __init__(self, *args, **kwargs):
            super(GroupAdminForm, self).__init__(*args, **kwargs)
    
            if self.instance and self.instance.pk:
                self.fields['users'].initial = self.instance.users.all()
    
    
    class GroupAdmin(admin.ModelAdmin):
        form = GroupAdminForm
    
        def save_model(self, request, obj, form, change):
            super(GroupAdmin, self).save_model(request, obj, form, change)
            if 'users' in form.cleaned_data:
                form.instance.user_set.set(form.cleaned_data['users'])
    
    
    admin.site.unregister(Group)
    admin.site.register(Group, GroupAdmin)
    
    0 讨论(0)
提交回复
热议问题