A bit of information about Github repositories, libraries, blogs, etc. that might be helpful is fine.
If you know of a better way to do this, please give me any advice you can.
I'm not familiar with the concept of django or English, so I may be wrong about some things.
○Purpose:
I would like to use the values of the existing TABLE fields (*1-3) in the existing DB being used in the existing system as is for user authentication (login with ID and password).
If possible, I would like to make it expandable for later use.
○Other restrictions:
In the current situation, if the authentication process can be performed and information such as EmployeeId can be used while logging in, we think there is no problem.
(Adding/updating/deleting user information can be done using the existing system or by the administrator directly hitting the DB.
We believe that the ability to add, update, and delete user information on the django side is temporarily unnecessary.)Since the django system is not running yet, you can delete all you want from the DB migration history, standard django tables, etc.
We don't want to use the standard django tables or create additional tables for user authentication if possible.
○Current system status:
Currently, our in-house system is running on VB.NET3.5 + MS SQLServer2008 in the form of a desktop application.
I'm trying to migrate to a web app if possible, but I've hit a wall of errors in user authentication.
- EmployeeId and TmployeeTable.Pass of the existing table are currently used for authentication, so we want to reuse them.
- Employee's primary key is a compound key of Employee.EmployeeId and Employee.DepartmentCode.
- Employee does not use an intermediate Table.
Employees who have been transferred or who hold concurrent positions in multiple departments are present in multiple records.
In short. There are multiple records with the same EmployeeId and Pass.
○What I learned about user authentication:
- https://docs.djangoproject.com/ja/3.1/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
- https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
- How to use an existing table for user login in Django?
- merge django's auth_user with existing user table
- Django - Authenticate against existing DB
Other articles that might be related to this...
But the premises of most of the articles are.
When launching a new web service (existing users = 0)
OR user registration by the user himself is a prerequisite.
OR use email address and password + alpha for authentication.
or use a standard table (auth_user) created by django
and I couldn't find anything that matched my purpose.
○What I tried:
On the official django website
https://docs.djangoproject.com/ja/3.1/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
it’s highly recommended to set up a custom user model
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
In simpleisbetterthancomplex.com above, there was a method for Option 1 - Option 4.
-
Option 1: Using a Proxy Model
-
Option 2: Using One-To-One Link With a User Model (Profile)
-
Option 3: Creating a Custom User Model Extending AbstractBaseUser
-
Option 4: Creating a Custom User Model Extending AbstractUser
According to the official website, if you don't need to change the contents stored in the database,
you can use theI tried Option 1 because it said that I could create a proxy model.
As a result, I got the following error.
The code is partially described below.
Application Name : auth_try
Class name customized by inheriting from a django user class : CustomUser
# models.py
class Employee(models.Model):
employeecd = models.IntegerField(db_column='EmployeeId', primary_key=True) # Field name made lowercase.
password = models.IntegerField(db_column='Pass', blank=True, null=True) # Field name made lowercase.
departmentcd = models.IntegerField(db_column='DepartmentCD', blank=True, null=True) # Field name made lowercase.
class CustomUser(AbstractUser):
username = models.OneToOneField(Employee, db_column='EmployeeId', on_delete=models.DO_NOTHING, related_name='username')
password = models.OneToOneField(Employee, db_column='Pass', on_delete=models.DO_NOTHING, related_name='password')
class Meta:
managed = False
proxy = True
And When you do
python manage.py makemigrations auth_try
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'CustomUser.groups'.
HINT: Add or change a related_name argument to the definition for 'User.groups' or 'CustomUser.groups'.
In addition, there are three Reverse accessor for errors.
↓
I may be wrong, but I added to
# setting.py
AUTH_USER_MODEL = 'auth_try.CustomUser'
↓
python manage.py makemigrations auth_try
↓
python manage.py migrate
↓
django.db.utils.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server][SQL Server] Foreign key 'django_admin_log_user_id_c 564eba6_fk_auth_try_customuser_id' references an invalid table 'auth_try_customuser'. (1767) (SQLExecDirectW); [42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server] Could not create constraint. Please check for previous errors. (1750)")
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'CustomUser.groups'.
HINT: Add or change a related_name argument to the definition for 'User.groups' or 'CustomUser.groups'.
↓
python manage.py migrate --fake-initial
↓
python manage.py migrate
↓
python manage.py runserver
↓
When I tried to authenticate a user using a browser, I got a message that the object name 'auth_try_customuser' was invalid.
I checked the query, and it seems to refer to a table that doesn't exist because the FROM clause says auth_try_customuser.
↓
This is where I gave up on the option 1 method once and for all.
Do I need to use AUTH_USER_MODEL to override the method or something?
Next, we tried Option 4, and since we wanted to use an existing table, we tried Option 2 as well.
# models.py
class Employee(models.Model):
employeecd = models.IntegerField(db_column='EmployeeId', primary_key=True) # Field name made lowercase.
password = models.IntegerField(db_column='Pass', blank=True, null=True) # Field name made lowercase.
departmentcd = models.IntegerField(db_column='DepartmentCD', blank=True, null=True) # Field name made lowercase.
class CustomUser(AbstractUser):
username = models.OneToOneField(Employee, db_column='EmployeeId', on_delete=models.DO_NOTHING, related_name='username')
password = models.OneToOneField(Employee, db_column='Pass', on_delete=models.DO_NOTHING, related_name='password')
class Meta:
managed = False
# setting.py
AUTH_USER_MODEL = 'auth_try.CustomUser'
INSTALLED_APPS = [
# (topmost)
# Local app for auth
'auth_try.apps.AuthTryConfig',
...
]
↓
python manage.py makemigrations
↓
python manage.py migrate auth_try
↓
CommandError: App 'auth_try' does not have migrations. is displayed, but ignore it and continue.
↓
When the authentication process is performed,
If the AbstractUser or AbstractBaseUser property is used in the query, and the property value is missing, an error occurs.
# models.py
class CustomUser(AbstractUser):
# add
is_superuser = last_login = date_joined = is_active = first_name = email = last_name = is_staff = None
↓
When the login process is performed again
('42S22', "[42S22] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server] Column name 'id' is invalid. (207) (SQLExecDirectW); [42S22] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Statement could not be prepared. (8180)")(8180)).
I don't know where to go from here.
○Other questions:
In the first place, the approach to achieve the purpose of this project is What is the best approach to use?
Is the current approach the right one? I would like to know.
I know there may be a lot of useless or missing information.
If you know what I'm talking about, please advise me.
Thank you for reading this long article.