Drf: аутентификация без поля USERNAME_FIELD

`

extended from: Drf how to: simple-jwt authenticating without USERNAME_FIELD

Я пытался выяснить, как аутентифицировать пользователя с полем, которое не установлено как USERNAME_FIELD, и столкнулся с некоторыми проблемами, он позволяет мне вводить правильные поля данных, но он никогда не аутентифицирует

Я использую этот фрагмент из ответа на предыдущий вопрос:

class MyTokenStudentSerializer(TokenObtainPairSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['student_id'] = serializers.CharField(required=False)
        # self.fields['password'] = serializers.CharField(write_only=True, required=True)
        self.fields['password'] = PasswordField(trim_whitespace=False)

    username_field = 'student_id'
    auth_fields = ['student_id']


#login view extended from TokenObtainPairView
    class LoginStudentView(TokenObtainPairView):
        permission_classes = (AllowAny,)
        serializer_class = MyTokenStudentSerializer

производит

 {
        "detail": "No active account found with the given credentials"
 }

enter image description here

любые модификации будут высоко оценены.

Если вы используете стандартный ModelBackend, вам следует указать USERNAME_FIELD

class User(AbstractUser):
    USERNAME_FIELD = 'student_id'
    student_id = models.TextField(default="", unique=True) # Should be unique

Выход

~ $ curl -X POST "http://127.0.0.1:8000/api/auth/login-student/" -d "password=admin&student_id=stdnt"
{"refresh":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0MzcxMTgzMCwiaWF0IjoxNjQxMTE5ODMwLCJqdGkiOiJkY2MyNTEwZGRiNWE0ZTJmODllMDI2OWRkYWI5ZGVjNSIsInVzZXJfaWQiOjF9.c0QTdBhiPUf4yvPP0l3a-XQ0iD6kycECAdb6MAROY8g","access":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQxMTIzNDMwLCJpYXQiOjE2NDExMTk4MzAsImp0aSI6ImM0NjA0ZTlhMDBhNjQ5YjdhMTkxOGQ3OTJmOTMyYTJiIiwidXNlcl9pZCI6MX0.XoZXTJICE_PyZFXIIvsm3bci-e-O67AsYvIvY1ijNAo"}

Кроме того, вы можете написать свой собственный бэкенд auth и включить его в settings.py.

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'project.apps.auth.backends.MyCustomModelBackend',
]

Пример бэкенда

class MyCustomModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        student_id = kwargs.get("student_id")
        if student_id is None or password is None:
            return
        try:
            user = User.objects.get(student_id=student_id)
        except User.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            User().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

При таком подходе можно сохранить вход в систему через поле username. Также не следует указывать USERNAME_FIELD = 'student_id' в User модели

Вернуться на верх