Пользовательская аутентификация пользователя в DRF (Django Rest Framework) - PullRequest
0 голосов
/ 27 июня 2018

У меня уже есть рабочая регистрация auth.token с использованием класса User по умолчанию в django, но меня попросили добавить новое поле для Пользователя, я исследую такие вещи, как AbtractUser, AbstractBaseUser и т. Д. И я думаю, что лучшим решением будет метод OneToOneField.

Вот что я пытался сделать:

models.py:

class Usuario(models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE)
    es_tecnico = models.BooleanField(name = 'es_tecnico', default = False, blank = True)

serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username',
                  'password')

class UsuarioSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    class Meta:
        model = Usuario
        fields = ('user',
                  'es_tecnico')

    def create(self, validated_data):
        """
        Overriding the default create method of the Model serializer.
        :param validated_data: data containing all the details of student
        :return: returns a successfully created student record
        """
        user_data = validated_data.pop('user')
        user = UserSerializer.create(UserSerializer(), validated_data=user_data)
        usuario, created = Usuario.objects.update_or_create(user=user,
                            es_tecnico=validated_data.pop('es_tecnico'))
        return usuario

views.py:

class UsuarioViewSet(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = UsuarioSerializer
    queryset = Usuario.objects.all().filter(es_tecnico = False)


class TecnicoViewSet(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = UsuarioSerializer
    queryset = Usuario.objects.all().filter(es_tecnico = True)

Я хочу, чтобы это работало как можно проще, вот что я получаю, когда использую команду «python3 manage.py makemigrations»:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/__init__.py", line 365, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/base.py", line 332, in execute
    self.check()
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/base.py", line 364, in check
    include_deployment_checks=include_deployment_checks,
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/management/base.py", line 351, in _run_checks
    return checks.run_checks(**kwargs)
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/core/checks/registry.py", line 73, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/home/stalker/PycharmProjects/ingSoft/servidor/virenv/lib/python3.5/site-packages/django/contrib/auth/checks.py", line 29, in check_user_model
    if not isinstance(cls.REQUIRED_FIELDS, (list, tuple)):
AttributeError: type object 'Usuario' has no attribute 'REQUIRED_FIELDS'

Когда я пробую решения из других вопросов stackoverflow, я получаю эту ошибку:

AttributeError: type object 'Usuario' has no attribute 'USERNAME_FIELD'

если есть простой способ использования OneToOneField, я буду его ценить

Вот мнения, где у меня сейчас проблемы: views.py:

class Registrar(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = UsuarioSerializer

    def create(self, request, *args, **kwargs):
        #  Creando un nuevo usuario
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')

        user = Usuario.objects.create_user(username, email, password)
        user.save()

        token = Token.objects.create(user=user)

        return Response({'detail': 'El usuario fue creado con el token: ' + token.key})


class LoginView(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = LoginSerializer

    def create(self, request):
        serializer = LoginSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data["usuario"]
        django_login(request, user)
        token, created = Token.objects.get_or_create(user=user)
        return Response({"token": token.key}, status=200)

1 Ответ

0 голосов
/ 28 июня 2018

Здесь в вашем случае вы просто расширяете Django User модель , поэтому вы не должны переопределять AUTH_USER_MODEL.

Удалить эту строку кода из settings.py файла: AUTH_USER_MODEL = "pedidos.Usuario" и в вашем коде, если вы хотите использовать свою модель User, это то, что вы должны использовать:

from django.contrib.auth.models import User

(как мы уже говорили, вы просто расширяете модель Django User) или можете использовать удобную функцию get_user_model()

get_user_model ():

Вместо того, чтобы обращаться к пользователю напрямую, вам следует ссылаться на модель пользователя с помощью django.contrib.auth.get_user_model (). Этот метод возвращает текущую активную модель пользователя - пользовательскую модель пользователя, если она указана, или пользователь в противном случае.

Если вы хотите получить атрибут es_tecnico из User, вы можете использовать:

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='Juan')
>>> juan_es_tecnico = u.usuario.es_tecnico

или используя get_user_model():

>>> from django.contrib.auth import get_user_model
>>> my_user = get_user_model()
>>> u = my_user.objects.get(username='Juan')
>>> juan_es_tecnico = u.usuario.es_tecnico

Edit:

class Registrar(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = UsuarioSerializer

    def create(self, request, *args, **kwargs):
        #  Creando un nuevo usuario
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')

        user = User.objects.create_user(username, email, password)
        user.save()

        token = Token.objects.create(user=user)

        return Response({'detail': 'El usuario fue creado con el token: ' + token.key})

В Regitrar классе использовать User модель вместо Usuario.

Надеюсь, это поможет.

...