Make group mandatory when creating users

Hi,

I’m trying to overwrite the built in user creation page of the admin interface to make the group mandatory. This is how I adjusted the UserAdmin class:

# admin.py
  from django.contrib import admin
  from django.contrib.auth.admin import UserAdmin
  from django.contrib.auth import get_user_model
  from .forms import CustomUserChangeForm, CustomUserCreationForm

  User = get_user_model()


  class CustomUserAdmin(UserAdmin):
      form = CustomUserChangeForm
      add_form = CustomUserCreationForm
      fieldsets = (
          (None, {'fields': ('username', 'email', 'password', 'groups')}),
      )
      add_fieldsets = (
          (None, {'fields': ('username', 'email', 'password1', 'password2',
                             'groups')}),
      )


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

I tried different approaches as form to mimic the existing field but couldn’t replicate it. I also tried to look at the source code how the original definition for the original group field definition but couldn’t find it.

I appreciate any help / hints. Thank you :slight_smile:

Welcome @a-zen !

Keep in mind that the User < - > Group relationship is a many-to-many relationship between those two models. This means that there is no group field in User. The name group is a reference to a related object manager

What that means in this context is that in order to enforce some kind of group relationship, you’ll need to write some type of validation code to check to ensure that a group has been assigned. (I think you could add a clean method to the form to check to ensure that at least one group has been selected.)

Hi @KenWhitesell,

thank you very much. :slight_smile:

Yeah I was able to write a clean method that does the validation but it will display the error at the top of the page and not next to the field like for the other required fields. It’s okay but kinda not what I want. :slight_smile: It would also be fine if the admins could only assign one initial group so the following form kinda:

  class CustomUserCreationForm(UserCreationForm):
      groups = ModelChoiceField(
          queryset=Group.objects.all(),
          required=True,
          widget=forms.Select,
          label="Group",
      )

      def clean(self):
          cleaned_data = super().clean()
          cleaned_data['groups'] = [cleaned_data.get('groups')]
          return cleaned_data

this gives me more or less what I want in terms of the required field and what the admin should be able to select. What I don’t understand with that solution is why there is no automatic “Add new group” button like with the built-in field. My understanding was that Django adds this automatically for ForeignKey fields and I thought the group is one of these.

Can you shed any light into this? :slight_smile:

Thank you very much.

You can define it as a clean_xxx method on the field. As an input field, it’s not dependent upon other fields, so it can be a field-level clean and not a form-level clean.

Because what you’re creating here is a normal form field and not a field that is being created as a “ModelForm” field. You’re creating a field for the form yourself instead of allowing Django to create it. (Django doesn’t “know” that this new field is actually a reference to the model’s “groups” field.)
What I think you want to do here is just assign the widget to be used for that field in the form, possibly along with a custom clean_groups method. (There may be other changes necessary due to the differences between a foreign key and a many-to-many relationship.)

The groups field is not a Foreign Key, it’s an instance of a related field manager. There is no actual field named groups in the User model. Physically and functionally, there are many differences between a foreign key and a many-to-many relationship.