title: Django - Ability to assign permissions and groups for custom user model in admin console
body: <p>I just created a custom user model in django called Subscriber which inherits from AbstractBaseUser and PermissionsMixin. I then subclassed the necessary form classes in my admin.py file in order to register my custom user model with the admin console.</p>
  
  <p>First, I am a little confused on how the custom user model and permissions and groups fit together in django. I ran the <em>manage.py migrate</em> script after passing PermissionsMixin to my user model and it created two new tables in my database <em>subscriber_conf_subscriber_groups</em> and <em>subscriber_conf_subscriber_user_permissions</em>. Also, within the <a href="https://docs.djangoproject.com/en/1.7/topics/auth/customizing/" rel="nofollow noreferrer">django documentation</a> there was an example given where the Group model was unregistered from admin, so I did that as well.</p>
  
  <p>Now in the admin console I have just have a list of subscribers and forms for creating &amp; editing a subscriber. My question is, how do I add the ability to assign permissions and groups to my subscribers from the admin console? Is the new user model still associated with the built-in django permissions and groups at this point, or is this something that I have to code?</p>
  
  <p>Any clarification would be great.</p>
  
  <p><strong>models.py</strong></p>
  
  <pre><code>from django.db import models
  from django.contrib.auth.models import User
  from django.conf import settings
  from django.utils import timezone
  from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
  
  #Custom user manager
  class SubscriberManager(BaseUserManager):
  
  
      def create_user(self, email, first_name, last_name, dti_id, street_address1, 
          street_address2, city, state, full_zip, phone_number, password=None):
  
          #save 5 digit zip
          tmp_zip = full_zip.split("-")
          new_zip = tmp_zip[0]
  
          return self._create_user(email, first_name, last_name, dti_id, street_address1, 
              street_address2, city, state, new_zip, full_zip, phone_number, 
              False, False, password, 0)
  
      #utility function
      def _create_user(self, email, first_name, last_name, dti_id, street_address1,
          street_address2, city, state, zip_code, full_zip,
          phone_number, is_superuser, is_staff, password=None, account_updated=0):
  
          #define now
          now = timezone.now()
  
          if not email:
              raise ValueError('Users must have an email address')
  
          #use django to normalize the email address
          email = self.normalize_email(email)
  
          user = self.model(
              email = email,
              first_name = first_name,
              last_name = last_name,
              dti_id = dti_id,
              street_address1 = street_address1,
              street_address2 = street_address2,
              city = city,
              state = state,
              zip_code = zip_code,
              full_zip = full_zip,
              phone_number = phone_number,
              account_updated = account_updated,
              is_admin = is_staff, 
              is_active = True,
              is_superuser = is_superuser,
              date_joined = now, 
              last_modified = now)
          user.set_password(password)
          user.save(using=self._db)
  
          return user
  
      #create superuser override
      def create_superuser(self, email, first_name, last_name, dti_id, street_address1,
          street_address2, city, state, full_zip, phone_number, password):
  
          #either need to create needed fields or require them in user model
  
          tmp_zip = full_zip.split("-")
          new_zip = tmp_zip[0]
  
          return self._create_user(email, first_name, last_name, dti_id, street_address1, 
              street_address2, city, state, new_zip, full_zip, phone_number, 
              True, True, password, 0)
  
  
  #Custom user definition
  class Subscriber(AbstractBaseUser, PermissionsMixin):
      email = models.EmailField(max_length=254, unique=True, db_index=True)
      first_name = models.CharField(max_length=100)
      last_name = models.CharField(max_length=100)
      dti_id = models.IntegerField(default=0)
      street_address1 = models.CharField(max_length=100)
      street_address2 = models.CharField(max_length=100, blank=True)
      city = models.CharField(max_length=100)
      state = models.CharField(max_length=10)
      zip_code = models.CharField(max_length=5)
      full_zip = models.CharField(max_length=10, blank=True)
      account_updated = models.BooleanField(default=0)
      phone_number = models.CharField(max_length=20)
  
      last_modified = models.DateTimeField(default=timezone.now)
      date_joined = models.DateTimeField(default=timezone.now)
      is_active = models.BooleanField(default=True)
      is_admin = models.BooleanField(default=False)
  
      objects = SubscriberManager()
  
      USERNAME_FIELD = 'email'
  
      REQUIRED_FIELDS = [
          'first_name', 
          'last_name', 
          'dti_id', 
          'street_address1',
          'street_address2',
          'city',
          'state',
          'full_zip',
          'phone_number',
      ]
  
      # define custom perms
      class Meta:
          permissions = (
              ("view_web", "Can access SJ web content"),
              ("view_web_e_edition", "Can access SJ e-edition content"),
              ("view_wweb", "Can access weekly web content"),
              ("view_wweb_e_edition", "Can access weekly e-edition content"),
  
              #.... more permissions
              #may be able to use this for subscriber coupons and such
          )
  
      def get_full_name(self):
          return self.email
  
      def get_short_name(self):
          return self.email
  
      def __unicode__(self):
          return self.email
  
      def has_perm(self, perm, obj=None):
          return True
  
      def has_module_perms(self, app_label):
  
          return True
  
      @property
      def is_staff(self):
          return self.is_admin
  </code></pre>
  
  <p><strong>admin.py</strong></p>
  
  <pre><code>from django import forms
  from django.contrib import admin
  from django.contrib.auth.models import Group
  from django.contrib.auth.admin import UserAdmin
  from django.contrib.auth.forms import ReadOnlyPasswordHashField
  
  from subscriber_conf.models import Subscriber
  
  
  class SubscriberCreationForm(forms.ModelForm):
  
      password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
      password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
  
      class Meta:
          model = Subscriber
          fields = (
              'email', 
              'first_name',
              'last_name',
              'dti_id',
              'street_address1',
              'street_address2',
              'city',
              'state',
              'zip_code',
              'full_zip',
              'phone_number',
          )
  
      def clean_password2(self):
          password1 = self.cleaned_data.get("password1")
          password2 = self.cleaned_data.get("password2")
          if password1 and password2 and password1 != password2:
              raise forms.ValidationError("Passwords don't match")
          return password2
  
      def save(self, commit=True):
          user = super(SubscriberCreationForm, self).save(commit=False)
          user.set_password(self.cleaned_data["password1"])
  
          #perhaps do some stuff with times and dates
  
          if commit:
              user.save()
          return user
  
  
  class SubscriberChangeForm(forms.ModelForm):
      password = ReadOnlyPasswordHashField()
  
      class Meta:
          model = Subscriber
          fields = (
              'email',
              'password',
              'first_name',
              'last_name',
              'dti_id',
              'street_address1',
              'street_address2',
              'city',
              'state',
              'zip_code',
              'full_zip',
              'phone_number',
              'account_updated',
              'is_admin', 
              'is_active',
              'is_superuser',
              'date_joined', 
              'last_modified'
              )
  
      def clean_password(self):
          return self.initial["password"]
  
  
  class SubscriberAdmin(UserAdmin):
      form = SubscriberChangeForm
      add_form = SubscriberCreationForm
  
      date_hierarchy = 'last_modified'
  
  
      list_display = ('email', 'first_name', 'last_name',
      'street_address1', 'street_address2', 'city', 'state',
      'zip_code', 'full_zip', 'phone_number', 'dti_id', 'account_updated',
      'last_modified', 'is_admin', 'is_superuser')
      list_filter = ('is_admin', 'is_superuser', 'account_updated',)
      fieldsets = (
          (None, {'fields': ('email', 'password')}),
          ('Personal info', {'fields': ('first_name', 'last_name', 'street_address1', 
              'street_address2', 'city', 'state', 'zip_code', 'full_zip',
              'phone_number', 'account_updated',)}),
          ('Permissions', {'fields': ('is_admin',)}),
      )
  
      add_fieldsets = (
          (None, {
              'classes': ('wide',),
              'fields': ('email', 'first_name', 'last_name', 'street_address1', 'street_address2',
              'city', 'state', 'full_zip', 'phone_number', 'password1', 'password2')}
          ),
      )
      search_fields = ('email', 'street_address1', 'street_address2', 'first_name',
          'last_name',)
      ordering = ('dti_id',)
      filter_horizontal = ()
  
  
  admin.site.register(Subscriber, SubscriberAdmin)
  admin.site.unregister(Group)
  </code></pre>
  
  <p><img src="https://i.stack.imgur.com/qszw1.png" alt="My django admin console"></p>