-1

I cannot for the life of me figure out what I'm doing wrong here, any help would be very much appreciated!

The Goal: We have admins and appraisers signing up on the site. Admins can of course do everything you'd expect from the /admin site and appraisers have their own site, /portal. What I'm trying to do now is improve my current model so that I can add more fields to the appraiser users. The admin user's fields are a subset of the appraiser user's fields.

The Error:

SystemCheckError: System check identified some issues:

ERRORS:
accounts.Appraiser.groups: (fields.E304) Reverse accessor for 'accounts.Appraiser.groups' clashes with reverse accessor for 'accounts.Admin.groups'.
    HINT: Add or change a related_name argument to the definition for 'accounts.Appraiser.groups' or 'accounts.Admin.groups'.
accounts.Appraiser.user_permissions: (fields.E304) Reverse accessor for 'accounts.Appraiser.user_permissions' clashes with reverse accessor for 'accounts.Admin.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'accounts.Appraiser.user_permissions' or 'accounts.Admin.user_permissions'.
accounts.Admin.groups: (fields.E304) Reverse accessor for 'accounts.Admin.groups' clashes with reverse accessor for 'accounts.Appraiser.groups'.
    HINT: Add or change a related_name argument to the definition for 'accounts.Admin.groups' or 'accounts.Appraiser.groups'.
accounts.Admin.user_permissions: (fields.E304) Reverse accessor for 'accounts.Admin.user_permissions' clashes with reverse accessor for 'accounts.Appraiser.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'accounts.Admin.user_permissions' or 'accounts.Appraiser.user_permissions'.

Before anyone asks here is my AUTH_USER_MODEL setting :) AUTH_USER_MODEL = "accounts.Admin"

The Admin/Appraiser users and their managers:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager


class AppraiserManager(UserManager):

    @property
    def licensed_appraisers(self):
        ...
        ...


class Appraiser(AbstractUser):

    license_num = models.CharField(
        max_length=25, verbose_name="Appraiser License #", blank=False, null=False
    )
    license_expiration = models.DateField(
        verbose_name="Appraiser License Expiration Date", blank=False, null=False,
    )
    email = models.EmailField(
        max_length=254,
        blank=False,
        null=False,
    )
    objects = AppraiserManager()

    @staticmethod
    def get_or_create(
        first_name: str,
        last_name: str,
        license_num: str,
        license_exp: date,
        email: str,
        username: str = None,
    ):
        first_name = first_name.strip()
        last_name = last_name.strip()
        license_num = license_num.strip()
        email = email.strip().lower()
        group = group_helpers.get_or_create_appraisers_group()
        user, created = Appraiser.objects.get_or_create(
            first_name=first_name,
            last_name=last_name,
            license_num=license_num,
            license_exp=license_exp,
            email=email,
            username=username or f"{first_name.lower()}.{last_name.lower()}",
            is_active=True,
            is_superuser=False,
            is_staff=True,
        )
        user.save()
        group.user_set.add(user)


class AdminManager(UserManager):
    pass


class Admin(AbstractUser):
    email = models.EmailField(
        max_length=254,
        blank=False,
        null=False,
    )
    additional_info = models.OneToOneField(
        Appraiser, unique=True, on_delete=models.DO_NOTHING, related_name="admin"
    )
    objects = AdminManager()

Their relevant forms (they aren't complete for my purposes, but I don't think anything is missing to cause this?):

from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.forms import UserCreationForm

from .models import Appraiser
from .models import Admin


class AppraiserCreationForm(UserCreationForm):
    class Meta:
        model = Appraiser
        fields = ("username", "email")


class AppraiserChangeForm(UserChangeForm):
    class Meta:
        model = Appraiser
        fields = ("username", "email")


class AdminCreationForm(UserCreationForm):
    class Meta:
        model = Admin
        fields = ("username", "email")


class AdminChangeForm(UserChangeForm):
    class Meta:
        model = Admin
        fields = ("username", "email")

The accounts app's admin.py file:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .forms import AppraiserChangeForm
from .forms import AppraiserCreationForm
from .forms import AdminChangeForm
from .forms import AdminCreationForm
from .models import Appraiser
from .models import Admin


class AppraiserAdmin(UserAdmin):

    add_form = AppraiserCreationForm
    form = AppraiserChangeForm
    model = Appraiser
    list_display = [
        "username",
    ]


class AdminAdmin(UserAdmin):

    add_form = AdminCreationForm
    form = AdminChangeForm
    model = Admin
    list_display = [
        "username",
    ]


admin.site.register(Admin, AdminAdmin)

I can provide more code/info as needed/requested!

ep_dev
  • 81
  • 1
  • 3
  • did you set auth_user_model in the settings.py? – Sumithran Aug 15 '21 at 07:20
  • [AbstractUser](https://github.com/django/django/blob/main/django/contrib/auth/models.py#L321) defines model fields with foreign keys and inheriting them like this with two models will cause those foreign key's related names to clash. – Brian Destura Aug 15 '21 at 08:04

1 Answers1

0

First of you can't use AbstractUser models two times in your project as you already pointed your settings.py file what is your authentication models.

The best approach of using one models and just in that models add additional flags

is_admin and is_appraiser and then defin two seperate models for your admin user and appriaser user with pointing OneToOneField

When you are gonna handle login/signup job, you handle based on flag.

Here you go for similar solution:

How to use multiple user models in Django?