【问题标题】:Authentication by extending User model in DRF (Django Rest Framework)通过在 DRF 中扩展用户模型进行身份验证(Django Rest Framework)
【发布时间】:2020-04-05 18:58:51
【问题描述】:

我已经使用 django 默认用户类进行了有效的 auth.token 注册,但我被要求向用户添加一个新字段,我调查的是 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)

序列化器.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 安装的简单方法,我会欣赏它

这是我现在遇到问题的视图: 视图.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)

【问题讨论】:

  • settings.py 文件中你是否设置AUTH_USER_MODEL config var?
  • 我已经有一个 AUTH_USER_MODEL = pedidos.Usuario
  • pedidos.Usuario 不是有效的用户模型,因此必须从您的设置中删除“AUTH_USER_MODEL = pedidos.Usuario”。见docs.djangoproject.com/en/2.1/topics/auth/customizing/…
  • 我有一行代码未删除,现在当我注册用户时,我在 API 中收到此错误:'Manager' 对象没有属性'create_user'。如果您可以为有相同问题的人提供一个有用的帖子或文档的链接,我将提供很多帮助

标签: python django authentication django-rest-framework token


【解决方案1】:

在你的例子中你只是extending Django User model,所以你不应该覆盖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() 引用用户模型。 该方法将返回当前活跃的用户模型——自定义 如果指定了用户模型,则为用户模型,否则为用户。

如果您想获取User 的属性es_tecnico,您可以使用:

>>> 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

编辑:

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})

Registrar 类中使用User 模型而不是Usuario

我希望这会有所帮助。

【讨论】:

  • 我明白,但问题是,我需要使用 Django Rest Framework,如果我使用 django Admin 添加一些新的“Usuarios”并且我的视图的查询集询问“给我带来所有的”Usuarios where “es_tecnico = True”,它有效,我的问题是我找不到用 DRF 序列化这个“自定义用户”的方法
  • @JuanEsteban 你的序列化器UserSerializerUsuarioSerializer 看起来不错,有什么问题?再次Usuarios 不是自定义用户只是扩展用户(称为配置文件模型)。见extending the existing user model
  • 我编辑了问题,最后我添加了在扩展 django 用户类之前运行良好的视图
  • @JuanEsteban 为了清楚起见,您现在遇到的问题或错误是什么?
  • 异常类型:AttributeError 异常值:'Manager' 对象没有属性'create_user'
猜你喜欢
  • 2020-07-16
  • 1970-01-01
  • 2013-05-03
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 2018-02-12
  • 2018-07-10
  • 2017-04-13
相关资源
最近更新 更多