Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Django admin中编辑组对象时将用户对象分配给组_Django_Django Admin_Membership_Usergroups - Fatal编程技术网

在Django admin中编辑组对象时将用户对象分配给组

在Django admin中编辑组对象时将用户对象分配给组,django,django-admin,membership,usergroups,Django,Django Admin,Membership,Usergroups,在用户对象(编辑用户)的默认Django管理视图中,可以编辑用户的组成员身份。如果我也希望这样呢?即,在组编辑页面中,可以选择属于正在编辑的组的用户 正如我看到的,Django没有从组到用户对象的多个映射,这使得不可能(?)为这种特殊情况实现ModelAdmin类。如果我可以创建一个额外的UsersOfGroup模型类,并在Django的Group模型的ManyToMany字段中将其用作through属性,那么有一种方法 任何想法,这是可以实现使用ModelAdmin技巧,还是我只需要为编辑组创

在用户对象(编辑用户)的默认Django管理视图中,可以编辑用户的组成员身份。如果我也希望这样呢?即,在组编辑页面中,可以选择属于正在编辑的组的用户

正如我看到的,Django没有从组到用户对象的多个映射,这使得不可能(?)为这种特殊情况实现ModelAdmin类。如果我可以创建一个额外的UsersOfGroup模型类,并在Django的Group模型的ManyToMany字段中将其用作through属性,那么有一种方法

任何想法,这是可以实现使用ModelAdmin技巧,还是我只需要为编辑组创建一个自定义视图

我已经检查了另外两个问题,但它们的作用并不完全相同:

更新: 克里斯的回答就快到了。:)该组具有对用户集的引用,但称为用户集,而不是用户集。以下是我所做的改变:

if self.instance and self.instance.pk:
    self.fields['users'].initial = self.instance.user_set.all()


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)

如果您添加新组并同时向组中添加用户,则上述保存方法将不起作用。问题是新组不会被保存(管理员使用commit=False)并且没有主键。由于save_m2m()的目的是允许调用视图处理保存的m2m对象,因此我创建了一个save对象,将旧的save_m2m方法包装到一个新方法中

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

下面是一种更简单的方法,它使用Django的InlineModelAdmin对象()


我使用的是Django 2.1,使用的是Chris发布的解决方案,但正如Cedric所解释的,当添加一个新组并且同时将用户添加到新组时,该解决方案将不起作用。不幸的是,他的代码也没有帮助,但我可以使用下面这个修改过的版本来让它工作

编辑:我加入了用户am70的建议(谢谢!),并使用了
get\u user\u model()
。这段代码继续使用Django3.1,并已使用Python3.6、3.7和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)

谢谢,这就成功了!我不得不对它进行一些编辑,但基本上这就是解决方案。上面的代码对我很有用。我要做的唯一更改是将self.instance.users.all()更改为self.instance.user\u set.all()。这段代码不起作用,因为当您将用户添加到组中并保存时,您的更改会被保存。下面由tomka提供的解决方案确实适用于recente Django,PythonI可以确认这是处理M2M关系的正确方法。这是Django 3中唯一一个使用AFAICT的方法。另外,我建议不要导入
User
,而是从django.contrib.auth导入get\u User\u模型导入
;User=get\u User\u model()
这是一个很好的建议,谢谢。我把它包括在答案中。
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)
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)