在 Djoser 和 Rest Framework 中使用自定义字段注册用户

Posted

技术标签:

【中文标题】在 Djoser 和 Rest Framework 中使用自定义字段注册用户【英文标题】:Register User with custom fields in Djoser and Rest Framework 【发布时间】:2017-05-25 13:32:09 【问题描述】:

我正在尝试使用来自Djoser 的“注册”端点。它工作正常,但我需要更多的字段,而不仅仅是“用户名”、“电子邮件”和“密码”。 我已经看到了这个question,并且确实可以看到我想要的字段(在可浏览的 API 中)。但是当我尝试发布它时,我得到了这个错误

/account/register/ 配置不正确,无法解析 URL 对于使用视图名称“用户详细信息”的超链接关系。你可以 未能在您的 API 中包含相关模型,或不正确 在该字段上配置了lookup_field 属性。

而且我不知道出了什么问题。

我的 models.py 看起来是这样的:

from django.db import models


class User(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    email = models.CharField(max_length=100, blank=False)
    name = models.CharField(max_length=100, blank=False)
    last_name = models.CharField(max_length=100, blank=False)
    birthday = models.CharField(max_length=15, blank=False)
    password = models.CharField(max_length=100, blank=False)

    class Meta:
        ordering = ('created',)

serializers.py

from rest_framework import serializers
from users.models import User


class UserSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = User
        fields = ('url', 'id', 'email', 'name', 'last_name', 'birthday', 'password')

我的意见.py

from users.models import User
from users.serializers import UserSerializer
from rest_framework import viewsets


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

我在 settings.py 中添加了:

DJOSER = 
    ...
    'SERIALIZERS': 
        'user_registration': 'users.serializers.UserSerializer',
    ,

编辑

应用程序/urls.py

from django.conf.urls import url, include
from users import views
from rest_framework.routers import DefaultRouter
from rest_framework.schemas import get_schema_view

# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'users', views.UserViewSet)

schema_view = get_schema_view(title='Pastebin API')

# The API URLs are now determined automatically by the router.
# Additionally, we include the login URLs for the browsable API.

urlpatterns = [
    url(r'^', include(router.urls)),
    url('^schema/$', schema_view),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

api/urls.py

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework_jwt import views as jwt_views
from rest_framework import routers

router = routers.DefaultRouter()

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include(router.urls)),
    url(r'^account/', include('djoser.urls')),
    url(r'^auth/login/', jwt_views.obtain_jwt_token, name='auth'),
]

有人有想法吗?

【问题讨论】:

尝试将您的“用户”模型重命名为“扩展用户”之类的名称,并在其字段中包含与 django.contrib.aut.models.User 模型的 OneToOne 关系。如果效果好,我会解释原因。 另外,我在序列化程序中看不到 HyperlinkedIdentityField... 嗨,孩子,谢谢。我是 Django 和 Rest Framework 的新手。 include to it's fields a OneToOne relation with django.contrib.auth.models.User model 是什么意思?我看了here,但我不知道该怎么做。 暂时不用考虑,我想我知道真正的原因。你能告诉我你的urls.py文件和urlpatterns映射到UserViewSet的条目吗? 完成。再次感谢你。也许有问题。我认为我在网址中合并了太多。 【参考方案1】:

异常很明显:Django 无法通过 user-detail 名称解析 URL。它尝试这样做是因为您已经从 serializers.HyperlinkedModelSerializer 使用 url 字段创建了一个扩展序列化程序,该字段应包含指向您的特定用户对象的链接。

我看到的问题是您的主要urls.py 不包括api 网址,它们都重复并连接起来有点奇怪。我会重写如下(假设你也有user app):

urls.py:

from django.conf.urls import url, include
from django.contrib import admin

from rest_framework.schemas import get_schema_view
from rest_framework_jwt import views as jwt_views

schema_view = get_schema_view(title='Pastebin API')

urlpatterns = [
    url('^schema/$', schema_view),
    url(r'^admin/', admin.site.urls),
    url(r'^user/', include('user.urls')),
    url(r'^account/', include('djoser.urls')),
    # Not sure if you need both:
    url(r'^auth/login/', jwt_views.obtain_jwt_token, name='auth'),
    url(
        r'^api-auth/',
        include('rest_framework.urls', namespace='rest_framework')),
]

用户应用urls.py

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter

from .views import UserViewSet

router = DefaultRouter()
router.register(r'users', UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]

不过,我不确定您为什么需要另一个名为 api 的应用程序。

如果没有帮助,请尝试在namespacing the router 上查看这篇文章。

【讨论】:

是的,很好。我需要更多地了解它,但它确实有效。 :) 谢谢 :)【参考方案2】:

您可以在 django 2.0 中使用 djoser 通过继承 AbstractUser 来创建自定义用户,这会针对您的像这样的应用程序:

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    FUNCTION = 1
    VIEWER = 2
    TECHNICIAN = 3
    ROLE_CHOICES = (
        (FUNCTION, 'Functional'),
        (VIEWER, 'Viewer'),
        (TECHNICIAN, 'Technician'),
    )
    role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
    REQUIRED_FIELDS = ["email", "role"]

然后在 settings.py 中定义用户新用户类: AUTH_USER_MODEL = 'app_name.User'

请注意,我在这里定义了我的 REQUIRED_FIELDS。所以当我使用 djoser API /me/ 时,它会给我所有必填字段。

【讨论】:

是否可以将作为必填字段添加为与用户模型相关的模型的一部分? (例如,在注册时添加用户地址,这是它自己的单独模型;并在注册时创建与 FK 连接的 Address 表身份给刚刚注册的用户)

以上是关于在 Djoser 和 Rest Framework 中使用自定义字段注册用户的主要内容,如果未能解决你的问题,请参考以下文章

DRF:如何将 django-rest-framework-jwt 集成到 Djoser

Django Rest Framework djoser 激活问题

django-rest-auth vs djoser,哪一个用于社交身份验证?

带有 Knox 代币的 DRF 的 Djoser

如何从 consumer.py django 访问用户信息?

Django rest framework 身份和权限验证