0

I want to save this AbstractUser in my model.

#app_name members
#models.py
class User(AbstractUser):
        is_student = models.BooleanField(default=False)
        is_teacher = models.BooleanField(default=False)

settings.py

INSTALLED_APPS = [
 #deful django app...
 #others app....
 'members',

]

AUTH_USER_MODEL = 'members.User'

when trying to save before go makemigrations getting this error

django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

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

why getting this error? how to solve it?

I also tried this AUTH_USER_MODEL = 'myAppName.myClassName' and getting this error

django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
blog.Blog.author: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
        HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
blog.BlogComment.user: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
        HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
blog.GlobalNotifications.user: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
        HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
notifications.Notifications.receiver: (fields.E301) Field defines a 
relation with the model 'auth.User', which has been swapped out.    
        HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
notifications.Notifications.sender: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.      
        HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
boyenec
  • 1,405
  • 5
  • 29
  • Possible duplicate of https://stackoverflow.com/questions/49189402/auth-user-groups-fields-e304-reverse-accessor-for-user-groups-clashes-with – gmdev Jul 26 '21 at 18:47
  • @gmdev I saw the question and tried `AUTH_USER_MODEL = 'YourAppName.YourClassName'` but didn't wok – boyenec Jul 26 '21 at 18:50
  • Is the app with your `User` in `INSTALLED_APPS`? – gmdev Jul 26 '21 at 18:55
  • gmdev no. I am using `User` an model name in my app which name is members. – boyenec Jul 26 '21 at 18:57
  • The app you are linking to `AUTH_USER_MODEL` needs to be in your `INSTALLED_APPS` for Django to recognize it. Otherwise, it will not work. – gmdev Jul 26 '21 at 18:58
  • so I need to just add name `User` in my settings.py app without doing `python manage.py makemigrations and migrate`? – boyenec Jul 26 '21 at 19:00
  • I believe you need to add the `members` to `INSTALLED_APPS` in `settings.py`, and then set `AUTH_USER_MODEL` to `"members.User"` (or whatever the dotted path to the `User` model is). You may need to delete the previous migration and remigrate. – gmdev Jul 26 '21 at 19:02
  • @ gmdev I said in comment I am using `User` in my members app. Which I included in my settings.py. may be you misunderstood – boyenec Jul 26 '21 at 19:03
  • Could you please edit your question to show your `INSTALLED_APPS` and `AUTH_USER_MODEL`? – gmdev Jul 26 '21 at 19:11
  • Have you deleted the failed migration from the `migrations/` folder and tried again? – gmdev Jul 26 '21 at 19:45
  • @gmdev yes I did – boyenec Jul 26 '21 at 20:28

2 Answers2

0
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

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

Basically this error is saying that you need to have unqiue related_name as related name insure there is no conflict between field. It can not find settings.AUTH_USER_MODEL because you did not run makemigrations

If you want to create custom user with is_student, is_teacher , you can follow the code below cuz this is how I like to create custom users

You need to run makemigrations and migrate before you can test it! Or you can create separated app to see if this custom user suites your needs.

in utils.py

from django.db import models
import random
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _


class IntegerRangeField(models.IntegerField):
    """ 
      This model handels :
          - Creating custom IntegerField with min/ max value.
          - Used in Users class, employee_number.
          - Gives each employee exactly 4 digits integer.
          - Can be edited in future if company grows in size.
        ...
        Attributes:
        ----------
        min_value :
            minimum number.
        max_value:
            maximum number.
        Methods:
        formfield(self, **kwargs):
          - create new defaults for IntegerField then update them.
    """
    def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
        self.min_value, self.max_value = min_value, max_value
        models.IntegerField.__init__(self, verbose_name, name, **kwargs)
    def formfield(self, **kwargs):
        defaults = {'min_value': self.min_value, 'max_value':self.max_value}
        defaults.update(kwargs)
        return super(IntegerRangeField, self).formfield(**defaults)

# generate random number from 1000, 9000

def create_new_employee_number():
    return random.randint(1000,9999)



class CustomUserManager(BaseUserManager):
    """
    Custom user model manager where username is unique identifiers
    able to add more fields to Django basic User model.
    """
    def create_student(self, username, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        if not username:
            raise ValueError(_('The username must be set'))
        user = self.model(username=username, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, username, password, **extra_fields):
        """
        Create and save a SuperUser with the given email and password.
        """
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)
        extra_fields.setdefault('is_student', False)
        extra_fields.setdefault('is_teacher', False)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        return self.create_user(username, password, **extra_fields)

    def create_teacher(self, username, first_name, last_name,  password=None):
        if not username:
            raise ValueError("User must have an email")
        if not password:
            raise ValueError("User must have a password")
        if not first_name:
            raise ValueError("User must have a first name")
        if not last_name:
            raise ValueError("User must have a last name")

        user = self.model(
            email=self.normalize_email(username)
        )
        user.first_name = first_name
        user.last_name = last_name
        user.set_password(password)  # change password to hash
        user.is_admin = False
        user.is_staff = True
        user.save(using=self._db)
        return user

    
    def create_staffuser(self, username, first_name, last_name,  password=None):
        if not username:
            raise ValueError("User must have an email")
        if not password:
            raise ValueError("User must have a password")
        if not first_name:
            raise ValueError("User must have a first name")
        if not last_name:
            raise ValueError("User must have a last name")

        user = self.model(
            email=self.normalize_email(username)
        )
        user.first_name = first_name
        user.last_name = last_name
        user.set_password(password)  # change password to hash
        user.is_admin = False
        user.is_staff = False
        user.is_teacher=True
        user.save(using=self._db)
        return user

now in models.py


from django.db import models
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
import datetime
from .utils import (
    IntegerRangeField,
    CustomUserManager,
    create_new_employee_number
) 
ROLES_CHOICES = (
    ('ST', 'Student'),
    ('TC', 'Teacher')
)


class User(AbstractUser):
    """
      This model handels :
              - follows django docs on how to customizing user mode.
              - https://docs.djangoproject.com/en/3.2/topics/auth/customizing/
              - Creating new users into the database.
              - aumatically genearte JWT from the home/urls.py "rest_auth.registration.urls"
        ...
        Attributes:
        ----------
        username :
            unique string field, max_length is 50
        name:
            user first and last name.
        role:
            user role two options(ST: Student, TC: Teacher)
        id:
            unique randomly generated integer, editable by admin.
            uses custom field, more details about IntegerRangeField in utils.py
        Methods:
        __str__
            return a string repr of the user, username.
    """
    username = models.CharField(unique=True, max_length=50)
    name = models.CharField(max_length=50, blank=True, default="Employee")
    role = models.CharField(
        max_length=50, choices=ROLES_CHOICES,
        blank=False, null=False, default="ST",
        error_messages = {'invalid': "Role is two choices ADMIN or EM"}
       )
    id= IntegerRangeField(
        min_value=1000, max_value=9999, editable=True, blank=True,
        unique=True, default=create_new_employee_number,
        error_messages={'invalid': "employee_number is unique integer 1000-9999"}
        )

    objects = CustomUserManager()

    def __str__(self):
        return self.username

araldhafeeri
  • 179
  • 9
-1

I was getting error because my all models was using defult django User model:

author = models.ForeignKey(User,on_delete=models.CASCADE,max_length=100, related_name='author')

but it should be

author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,max_length=100, related_name='author')
boyenec
  • 1,405
  • 5
  • 29