Невозможно получить данные POST из запроса Django request.POST

Я пытаюсь проверить, что необходимые данные были включены в POST-запрос. У меня есть django бэкенд и vue3 фронтенд.

Вот мое представление django:

views.py

# Sign user in and issue token
@require_http_methods(['POST'])
def login(request: HttpRequest):
    if request.method == 'POST':
        # check that required fields were send with POST
        print(request.body)
        if {'username', 'password'} >= set(request.POST):  # <- evaluates as False
            print('missing required fields. INCLUDED: ' + str(request.POST))
            return JsonResponse(
                data={'message': 'Please provide all required fields.'},
                content_type='application/json',
                status=400)
        # check that username exists and password matches
        if (User.objects.filter(username=request.POST['username']).count() >
                0):
            user = User.objects.get(username=request.POST['username'])
            if user.password == request.POST['password']:
                # Delete previously issued tokens
                Token.objects.filter(user_id=user.id).delete()
                token = Token(user_id=user.id)
                token.save()
                return JsonResponse(data={'userToken': token.to_json()},
                                    content_type='application/json',
                                    status=200)
        else:
            return JsonResponse(
                data={'message': 'Incorrect username or password.'},
                content_type='application/json',
                status=400)
    else:
        return HttpResponseNotAllowed(permitted_methods=['POST'])

И мой запрос на аксиос

Login.vue

axios
  .post('http://localhost:8000/api/users/login', {
    'username': form.get('username'),
    'password': form.get('password'),
  }, {
    validateStatus: (status) => {
      return status !== 500
    },
  })
  .then((response) => {
    console.log(response.data)
    if (response.data.success) {
      // Commit token value to store
      store.commit('setToken', response.data.token)
 
      // Request user data ...

    } else {
      alert.message = response.data.message
      alert.type = 'error'
      document.querySelector('#alert')?.scrollIntoView()
    }
  })

Я вижу, что username и password установлены в request.body, но не в request.POST, как показано в журнале django.

December 01, 2021 - 17:40:29
Django version 3.2.9, using settings 'webserver.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
b'{"username":"site.admin","password":"password"}'
missing required fields. INCLUDED: <QueryDict: {}>
Bad Request: /api/users/login
[01/Dec/2021 17:40:30] "POST /api/users/login HTTP/1.1" 400 50
/Users/colby/Projects/emotions/backend/webserver/users/views.py changed, reloading.
Watching for file changes with StatReloader
Performing system checks...

Что я делаю неправильно?

Я подозреваю, что Axios автоматически устанавливает заголовок content-type: application/json, который означает, что тело запроса не содержит параметров HTTP POST, которые могут быть поняты Django.

Вы можете проверить это, напечатав request.headers, и, если проблема действительно в этом, решите ее следующим образом:

  1. Разбор тела запроса из JSON:
import json
data = json.loads(response.body.decode())
if {'username', 'password'} >= set(data):  # etc.
  1. Отправить данные как данные формы на стороне клиента:
var formData = new FormData();
formData.set("username", form.get("username"))
formData.set("password", form.get("password"))
axios
  .post('http://localhost:8000/api/users/login', {
    data: formData,
    headers: {'Content-Type': 'multipart/form-data' }
  })

Лично я бы рекомендовал решение 1, поскольку считаю его менее многословным и более простым в обслуживании, но это в основном зависит от ваших предпочтений и требований :)

Вернуться на верх