【问题标题】:Rename Django User fields重命名 Django 用户字段
【发布时间】:2020-02-06 08:22:08
【问题描述】:

我正在使用 Django 创建一个 API。我需要为用户创建一个登录。所以我使用了默认的 Django User 类和身份验证来做到这一点。
但是有一个问题。 LogIn 的 API(在 /users/login/ 端点中)使用以下格式定义:{"user":value, "pass":value}。
而Django给出的User模型有两个重要的字段:“用户名”和“密码”。
正如我之前所说,我希望他们成为“用户”而不是“用户名”,以及“通过”而不是“密码”。因为这就是 POST 请求中的 JSON 在前端的样子。
我知道我可以创建一个 RenameField,但这只会更改数据库中的列名,不会更改 Django 在 POST 请求正文中询问用户名和密码的方式。

我需要(在邮递员的 POST 请求中)发送 JSON 到 /users/login/ 端点,格式如下:{"user":value, "pass":value}。
但是 Django 用户模型不知道那些字段是什么,它不需要用户,它需要用户名,它不需要通过,它需要密码,所以我得到一个错误。
我需要以某种方式将给定 JSON 中的“用户”和“密码”键更改为“用户名”和“密码”。或者,更改用户模型中的字段名称。否则,响应将是:

{
    "username": [
        "This field is required."
    ],
    "password": [
        "This field is required."
    ]
}

因为,正如我所说,Django 正在获取“用户”和“密码”,但它无法识别这些键......它需要“用户名”和“密码”字段。
即:我需要以某种方式更改:

{
    "user": value,
    "pass": value
}

到:

{
    "username": value,
    "password": value
}

反之亦然。
我尝试不创建自己的 User 模型,并使用 Django 提供的模型,我认为创建一个不是一个好主意...
我想我可以添加一个名为 serializer.py 的新文件并在那里做一些事情,但我不确定如何做,而且我在文档中没有找到任何内容。

如果它们有用,这些是我的文件。
urls.py:

from rest_framework.authtoken.views import obtain_auth_token
from django.contrib import admin
from catanAPI.catan import views
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/login/', obtain_auth_token)
]

settings.py

INSTALLED_APPS = [
    #...
    'django.contrib.auth',
    'rest_framework',
    'rest_framework.authtoken'
    #...
]

AUTH_USER_MODEL = 'auth.User'

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ]
}

我知道这个问题可能很愚蠢,但我是 Django 新手,我正在努力学习。

【问题讨论】:

  • I need to change the keys in the JSON given in the request. 是什么意思?还有你是怎么得到的?你能分享一下代码吗?
  • @ruddra 我已经编辑了这个问题。感谢您的回答。
  • 我的问题是你想通过缩短名称来实现什么?您将不得不采取一整套解决方法来完成这项工作。
  • 我必须按照他们告诉我的那样实现 API。我不能使用长名称。我认为他们是故意这样做的。

标签: python django django-models django-rest-framework django-forms


【解决方案1】:

您可以编写自定义用户:

应用程序/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    """
    Custom User Model 
    """

    user = models.CharField(max_length=255, unique=True)
    pass_w = models.CharField(max_length=50)
    email = models.CharField(max_length=255, unique=True)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["user"]

    def __str__(self):
        return self.email

项目/settings.py

AUTH_USER_MODEL = 'application.User'

【讨论】:

  • 首先,“pass”是python的保留字,用来忽略一条指令,所以会报错。如果我将其重命名为“pass”或类似名称,则会引发另一个长错误。
  • SystemCheckError:系统检查发现了一些问题:错误:auth.User.groups:(fields.E304)“User.groups”的反向访问器与“User.groups”的反向访问器发生冲突。提示:向“User.groups”或“User.groups”的定义添加或更改related_name 参数。 auth.User.user_permissions:(fields.E304)“User.user_permissions”的反向访问器与“User.user_permissions”的反向访问器冲突。提示:在“User.user_permissions”或“User.user_permissions”的定义中添加或更改related_name 参数。
  • catan.User.groups:(fields.E304)“User.groups”的反向访问器与“User.groups”的反向访问器冲突。提示:向“User.groups”或“User.groups”的定义添加或更改related_name 参数。 catan.User.user_permissions:(fields.E304)“User.user_permissions”的反向访问器与“User.user_permissions”的反向访问器冲突。提示:在“User.user_permissions”或“User.user_permissions”的定义中添加或更改related_name 参数。
  • 您的AUTH_USER_MODEL 尚未设置。使用 AUTH_USER_MODEL = 'catan.User' 更新您的 settings.py
【解决方案2】:

我认为与其更改模型字段,不如更改视图。您可以覆盖ObtainAuthToken 视图,如下所示:

from django.utils.translation import gettext as _
# serializer
class CustomAuthTokenSerializer(serializers.Serializer):
    user = serializers.CharField(label=_("User"))

    def __init__(self, *args, **kwargs):
        super(CustomAuthTokenSerializer, self).__init__(*args, **kwargs)
        self.fields['pass'] = serializers.CharField(
            label=_("Pass"),
            style={'input_type': 'password'},
            trim_whitespace=False
        )
    def validate(self, attrs):
        username = attrs.get('user')
        password = attrs.get('pass')

        if username and password:
            user = authenticate(request=self.context.get('request'),
                                username=username, password=password)

            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
            # backend.)
            if not user:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = _('Must include "username" and "password".')
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs

 # view
 from rest_framework.authtoken.views import ObtainAuthToken

 class CustomObtainAuthToken(ObtainAuthToken):
     serailizer_class = CustomAuthTokenSerializer

 # urls
 path('users/login/', CustomObtainAuthToken.as_view())

【讨论】:

  • user = serializers.CharField(label=_("User")) NameError: name '_' is not defined
  • 另外,你使用“pass”作为变量名,你不能这样做。它是python的保留字。
  • @Octaviotastico,你是对的。请查看更新后的答案
  • 我刚刚发现它为什么不起作用。您在 views.py 文件中有错字:“serailizer_class= CustomAuthTokenSerializer”,它是序列化程序而不是 serailizer 哈哈哈
  • from django.contrib.auth import authenticate 解决了它
猜你喜欢
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
  • 2011-03-15
  • 2016-02-10
  • 2018-11-13
  • 2012-02-06
  • 2017-03-11
  • 1970-01-01
相关资源
最近更新 更多