Тестовый клиент Django отправляет значения в виде списка вместо строк
У меня проблема, я не уверен, упустил ли я что-то из виду, или просто делаю что-то неправильно. Я пытаюсь протестировать конечную точку, которая позволяет пользователю зарегистрироваться.
Моя модель:
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")
Serializer:
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:
В объекте HttpRequest атрибуты GET и POST являются экземплярами django.http.QueryDict, словареподобный класс, настроенный для работы с множественными значениями для одного и того же ключа.
Затем, если вы хотите получить доступ к этим элементам, используйте метод QueryDict.__getitem__
:
Итак, в вашем случае это было бы что-то вроде:
>>> request.POST['username']
test_user
>>> request.POST['password']
1234
Или если у вас несколько значений в queryparams, вы можете использовать QueryDict.getlist
:
>>> POST = QueryDict('user_ids=ID1&user_ids=ID2&user_ids=ID3&')
>>> POST.getlist('user_ids')
['ID1', 'ID2', 'ID3']
QueryDict: 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