【问题标题】:AttributeError: 'UserViewSet' object has no attribute 'user'AttributeError:“UserViewSet”对象没有属性“用户”
【发布时间】:2021-08-16 11:59:53
【问题描述】:

我目前有一个 API 端点,当我通过 Postman 手动向它发送请求时,它可以正常工作。我这样做的方式是运行:

GET /user/?fromid=1&toid=100

我现在正在尝试使用 factory-boy 设置单元测试,但由于出现错误,我无法让它工作。

到目前为止,关于单元测试的重要文件是:

urls.py

from django.urls import include, path
from rest_framework import routers
from rest_framework.schemas import get_schema_view

import views

router = routers.DefaultRouter()
router.register(r"user", views.UserViewSet, basename='user')

urlpatterns = [
    path('user', views.UserViewSet.as_view({'get': 'user'}), name='user')
]

test_user.py

import factory
from django.test import Client, TestCase
from django.urls import reverse
from factory import DjangoModelFactory, Faker
from models.user import User

class UserFactory(DjangoModelFactory):
    class Meta:
        model = User

class UserViewSetTest(TestCase):
    def setUp(self):
        client = Client()

    def test_user_list(self):
        response = self.client.get(reverse('user'), format='json')
        self.assertEqual(response.status_code, 200)

当使用上面的运行pytest时,我得到一个错误:

AttributeError: 'UserViewSet' 对象没有属性 'user'

我感觉 URL 中的参数不允许我在单元测试中按原样调用它,但我不确定。

正如我所提到的,我已经能够通过 Postman 向 API 发送请求,所以我不确定展示我的完整代码(即 ViewSet、模型和序列化程序)是否有用。值得一提的是,视图集目前只返回 Json 格式的用户列表。

编辑:

我已经能够在 Postman 上手动重新创建错误。如果我在没有指定 URL 参数的情况下创建请求,如下所示:

GET /user

我手动遇到同样的错误

AttributeError: 'UserViewSet' 对象没有属性 'user'

因此,我尝试在单元测试中更新我的reverse 命令以包含 URL 参数,如下所示:

response = self.client.get(reverse('user'), kwargs={'fromid':1, 'toid': 100}, format='json')

但我仍然收到相同的原始错误。

EDIT2:

我认为部分问题在于我调用reverse 的方式。 kwargs 参数不在实际的 reverse 函数中。我已将其修改为:

response = self.client.get(reverse('user', kwargs={'fromid':1, 'toid': 100}), format='json')

现在我的错误与 url 路径有关(我相信),因为现在我收到了一个新错误:

使用关键字参数 '{'fromid':1, 'toid': 100}' 为 'user' 反转 未找到。尝试了 1 种模式:['/user$']

我的(希望是最终的)问题是如何在我的path 中指定多个参数以接受 kwargs?我的端点当前被 URL 中的参数(fromid 和 toid)接受,因此我需要在下面的 path 元素中指定它。我该怎么做?

router.register(r"user", views.UserViewSet, basename='user')
    
urlpatterns = [
    path('user', views.UserViewSet.as_view({'get': 'user'}), name='user')
]

【问题讨论】:

  • 您传递给 url 用户的 user 是什么(在 as_view(..) 内)?
  • @ResleyRodrigues 抱歉,这是一个复制/粘贴错误。它应该是“用户”名称字符串。我还编辑了我的问题以包含更多信息。
  • 打开 shell python manage.py shell 并尝试反转 url。这可能不是你想要的。也许这些 kwargs 是针对 url 的……在此处发布您的视图集也将有所帮助,因为这就是错误所在。
  • 网址/user(失败)与/user/(成功)不同,注意尾部斜杠。 views.UserViewSet.as_view({'get': 'user'}) 你确定视图有一个方法user 吗?因为该字典应该将请求方法映射到将使用的视图集的方法。此外,您从未在向我们展示的代码中使用路由器...
  • @ResleyRodrigues 问题是,我可以手动发送请求,所以我不认为这可能与视图集有关,而与测试有关。我已经进一步编辑了我的问题。

标签: python django unit-testing django-rest-framework django-views


【解决方案1】:

drf routers 将使用类似的名称

basename+'-list'

用于生成带有 list 操作的 url。所以你的代码应该是:

response = self.client.get(reverse('user-list', kwargs={'fromid':1, 'toid': 100}), format='json')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 2021-04-19
    • 2021-11-22
    相关资源
    最近更新 更多