Django 测试客户端将值作为列表而不是字符串发送
Django Test Client sends values as a list instead of strings
我有一个问题,我不确定是我忽略了什么,还是只是做错了什么。我正在尝试测试允许用户注册的端点。
我的模特:
class Account(User):
objects = UserManager()
balance = models.FloatField(blank=True, default=0)
rank_position = models.IntegerField(blank=True, null=True)
rank_title = models.CharField(max_length=255, blank=True, default="Novice")
序列化器:
class AccountSerializer(ModelSerializer):
class Meta:
model = Account
fields = '__all__
查看:
@api_view(['POST'])
def register(request):
try:
acc = Account.objects.create(**request.POST)
acc_srl = AccountSerializer(acc)
return Response(data=acc_srl.data, status=status.HTTP_201_CREATED)
except Exception as e:
return Response(status=status.HTTP_400_BAD_REQUEST)
我正在尝试通过以下方式使用 Django 测试客户端:
class TestAuthentication(TestCase):
def setUp(self):
self.c = Client()
def test_register(self):
data = {'username': 'test_user', 'password': '1234'}
response = self.c.post('/api/register/', data)
print(response.json())
self.assertEqual(response.status_code, 201)
acc = Account.objects.get(username="test_user")
self.assertEqual(acc.username, "test_user")
self.assertTrue(isinstance(acc, User))
函数按预期运行,但奇怪的事情发生了。当我检查 request.POST
时,用户名和密码都是一个列表:
<QueryDict: {'username': ['test_user'], 'password': ['1234']}>
我很困惑,因为我不明白是什么导致了这种行为。
这是 Django 的内置函数,用于处理具有相同键的多个值。参见 docs。
而当你使用 Django 的测试客户端时 this.c.post
并在第二个参数中发送数据。然后 Django 会将其作为 URL 参数而不是 POST 主体发送。
因此您的请求将如下所示:'/api/register/?username=test_user&password=1234'
假设您使用 '/api/register/?username=test_user&password=1234&password=5486'
发送请求
然后你的 request.POST
看起来像:
<QueryDict: {'username': ['test_user'], 'password': ['1234', '5486']}>
所以,我认为您不必为此担心。
我认为这是 request.POST
的正常行为。因为您可以为同一参数执行具有多个值的 POST
:例如:/api/register/?username=user&username=admin
,所以您将拥有
<QueryDict: {'username': ['user', 'admin']}>
你可以在官方文档中查看:https://docs.djangoproject.com/en/3.2/ref/request-response/#django.http.QueryDict
如 Django 文档中所述:
In an HttpRequest object, the GET and POST attributes are instances of
django.http.QueryDict, a dictionary-like class customized to deal with
multiple values for the same key.
然后,如果您想访问这些项目,请使用 QueryDict.__getitem__
方法:
所以,在你的情况下,它会是这样的:
>>> request.POST['username']
test_user
>>> request.POST['password']
1234
或者如果您在查询参数上有多个值,您可以使用 QueryDict.getlist
:
>>> POST = QueryDict('user_ids=ID1&user_ids=ID2&user_ids=ID3&')
>>> POST.getlist('user_ids')
['ID1', 'ID2', 'ID3']
查询字典:https://docs.djangoproject.com/en/3.1/ref/request-response/#querydict-objects
QueryDict.__getitem__: https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.QueryDict.\_\_getitem\_\_
QueryDict.getlist: https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.QueryDict.getlist
我有一个问题,我不确定是我忽略了什么,还是只是做错了什么。我正在尝试测试允许用户注册的端点。
我的模特:
class Account(User):
objects = UserManager()
balance = models.FloatField(blank=True, default=0)
rank_position = models.IntegerField(blank=True, null=True)
rank_title = models.CharField(max_length=255, blank=True, default="Novice")
序列化器:
class AccountSerializer(ModelSerializer):
class Meta:
model = Account
fields = '__all__
查看:
@api_view(['POST'])
def register(request):
try:
acc = Account.objects.create(**request.POST)
acc_srl = AccountSerializer(acc)
return Response(data=acc_srl.data, status=status.HTTP_201_CREATED)
except Exception as e:
return Response(status=status.HTTP_400_BAD_REQUEST)
我正在尝试通过以下方式使用 Django 测试客户端:
class TestAuthentication(TestCase):
def setUp(self):
self.c = Client()
def test_register(self):
data = {'username': 'test_user', 'password': '1234'}
response = self.c.post('/api/register/', data)
print(response.json())
self.assertEqual(response.status_code, 201)
acc = Account.objects.get(username="test_user")
self.assertEqual(acc.username, "test_user")
self.assertTrue(isinstance(acc, User))
函数按预期运行,但奇怪的事情发生了。当我检查 request.POST
时,用户名和密码都是一个列表:
<QueryDict: {'username': ['test_user'], 'password': ['1234']}>
我很困惑,因为我不明白是什么导致了这种行为。
这是 Django 的内置函数,用于处理具有相同键的多个值。参见 docs。
而当你使用 Django 的测试客户端时 this.c.post
并在第二个参数中发送数据。然后 Django 会将其作为 URL 参数而不是 POST 主体发送。
因此您的请求将如下所示:'/api/register/?username=test_user&password=1234'
假设您使用 '/api/register/?username=test_user&password=1234&password=5486'
发送请求
然后你的 request.POST
看起来像:
<QueryDict: {'username': ['test_user'], 'password': ['1234', '5486']}>
所以,我认为您不必为此担心。
我认为这是 request.POST
的正常行为。因为您可以为同一参数执行具有多个值的 POST
:例如:/api/register/?username=user&username=admin
,所以您将拥有
<QueryDict: {'username': ['user', 'admin']}>
你可以在官方文档中查看:https://docs.djangoproject.com/en/3.2/ref/request-response/#django.http.QueryDict
如 Django 文档中所述:
In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key.
然后,如果您想访问这些项目,请使用 QueryDict.__getitem__
方法:
所以,在你的情况下,它会是这样的:
>>> request.POST['username']
test_user
>>> request.POST['password']
1234
或者如果您在查询参数上有多个值,您可以使用 QueryDict.getlist
:
>>> POST = QueryDict('user_ids=ID1&user_ids=ID2&user_ids=ID3&')
>>> POST.getlist('user_ids')
['ID1', 'ID2', 'ID3']
查询字典:https://docs.djangoproject.com/en/3.1/ref/request-response/#querydict-objects
QueryDict.__getitem__: https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.QueryDict.\_\_getitem\_\_
QueryDict.getlist: https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.QueryDict.getlist