Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 editing page one could select the users that belong to the group being edited.

As I see this, Django doesn't have a ManyToMany mapping from Group to User object which makes it impossible(?) to implement a ModelAdmin class for this particular case. If I could make an additional UsersOfGroup model class and use it in the Django's Group model's ManyToMany field as a through-attribute, there could be a way.

Any ideas, is this possible to implement using ModelAdmin tricks or do I just have to make a custom view for editing groups?

I have checked these two other questions, but they don't quite do the same thing:

Assigning a group while adding user in admin

and

Show group membership in admin

Updated: The answer from Chris was almost there. :) The group has a reference to the users set, but it's called user_set, not users. So these are the changes I made:

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

and

if group.pk:
    group.user_set = self.cleaned_data['users']
like image 851
Janne Avatar asked May 23 '11 12:05

Janne


People also ask

How do I restrict access to admin pages in Django?

Django admin allows access to users marked as is_staff=True . To disable a user from being able to access the admin, you should set is_staff=False . This holds true even if the user is a superuser. is_superuser=True .

How do you define groups in Django?

Django Admin Panel : In Admin Panel you will see Group in bold letter, Click on that and make 3-different group named level0, level1, level3 . Also, define the custom permissions according to the need. By Programmatically creating a group with permissions: Open python shell using python manage.py shell.


2 Answers

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
like image 76
Cedric Avatar answered Sep 28 '22 01:09

Cedric


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)
like image 29
Chris Pratt Avatar answered Sep 28 '22 03:09

Chris Pratt