简体   繁体   中英

How to use two fields as username in Django custom user model?

I have employee table (legacy) with fields Employee_no, Company_name and Password. How can i use my current table as Django user model? Employee_no is duplicate but combination with company_name, it will be unique.

I need to use employee_no and company_name as username to login.

Employee_no Company_name password
1 Apple any password
1 Samsung any password
2 Apple any password
3 Samsung any password
3 Google any password

Here is an Example.It will be used in case or email or phone number

        try:
            user_obj = User.objects.get(Q(email=email_or_mobile) | Q(mobile_number=email_or_mobile))
        except User.DoesNotExist:
            raise Exception("Invalid email or mobile number")
        if not user_obj.check_password(password):
            raise Exception("Invalid password")
        if user_obj.is_active:
           login(request,user)

Django enforce you to have a unique USERNAME_FIELD in User model in order to use all the features that it provides out of the box. But you can always customize it if you really need it (with a little extra work).

In your situation you need a User model with two fields that uniqueness define them. This implies having a Custom User model and implementing your custom Authentication Backend

For User model you should have something like this:


class User(AbstractUser):
    username = None
    employee_no = models.IntergerField()
    company_name = models.CharField(max_lenght=100)

    USERNAME_FIELD = "employee_no"  # Not really used, but required by Django
    
    # Completes custom User subclassing ...

    class Meta:
        # This is required for your design in order to have database integrity
        unique_together = ('employe_no', 'company_name')

If your try to run server with this user model you will get System check errors

You should add to your settings

SILENCED_SYSTEM_CHECKS = ["auth.E003", "auth.W004"]

Now you have to implement a custom auth backend in order to authenticate users against two fields. For that just subclass django.contrib.auth.backends.BaseBackend and implement your authentication logic.

Something like this:


class CustomBackend(BaseBackend):

    def authenticate(self, request, employee_no=None, company_name=None, password=None, **kwargs):

        if employee_no is None or company_name is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(employee_no=employee_no, company_name=company_name)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

And add this backend to your settings in the list of AUTHENTICATION_BACKENDS (dotted string path)

Finally you must ensure passing the right parameters in login view to authenticate method and be very carefull with other integrations that requires standar Django User model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM