Поле 'id' ожидало число, но получило dict при загрузке базы данных django
Я ищу способ сохранить вопрос, полученный из внешнего API, в модели Question
. Мой модуль views.py
делает это, запрашивая данные, основанные на выборе пользователем сложности вопроса, а затем отображает полученное в форме. Это довольно простой метод, но по какой-то причине я получаю Field 'id' expected a number but got {'type': 'multiple'...}
.
Я удалил код, который предназначался для создания синглтона другой модели, который мешал этой реализации из последнего ответа на этот вопрос. Затем я запустил ./manage.py makemigrations
и ./manage.py migrate
, чтобы отразить изменения, но исключение снова возникло. После этого я удалил migrations.py и их кэшированные файлы, чтобы запустить те же две команды, и ничего не изменилось.
Может ли кто-нибудь указать, что я упускаю или делаю неправильно?
models.py
from django.db import models
class Question(models.Model):
type = models.TextField()
difficulty = models.TextField()
category = models.TextField()
question = models.TextField()
correct_answer = models.TextField()
incorrect_answers = models.TextField()
views.py
from django.shortcuts import render, HttpResponse
from .forms import QuestionForm, QuestionLevelForm
from urllib.request import URLError
from .models import Question
import requests
def process_question(request):
if "level" in request.POST:
return fetch_question(request)
elif "answer" in request.POST:
return check_answer(request)
else:
form = QuestionLevelForm()
return render(request, "log/question.html", {"form": form})
def fetch_question(request):
match request.POST["difficulty"]:
case "easy":
url = "https://opentdb.com/api.php?amount=1&category=9&difficulty=easy&type=multiple"
case "medium":
url = "https://opentdb.com/api.php?amount=1&category=9&difficulty=medium&type=multiple"
case "hard":
url = "https://opentdb.com/api.php?amount=1&category=9&difficulty=hard&type=multiple"
try:
response = requests.get(url)
except URLError as e:
HttpResponse("Couldn't fetch data, try again")
else:
render_question(request, response.json())
def render_question(request, response):
content = response["results"][0]
question = {
"type": content["type"],
"difficulty": content["difficulty"],
"category": content["category"],
"question": content["question"],
"correct_answer": content["correct_answer"],
"incorrect_answers": content["incorrect_answers"],
}
form = QuestionForm(question)
model = Question(question)
model.save()
context = {"question": question, "form": form}
render(request, "./log/templates/log/question.html", context)
test_views.py
from django.http import HttpRequest
from django.test import TestCase, Client
from .. import views
client = Client()
class QuestionTest(TestCase):
def test_page_load(self):
response = self.client.get("/log/question")
self.assertEqual(response["content-type"], "text/html; charset=utf-8")
self.assertTemplateUsed(response, "log/question.html")
self.assertContains(response, "Choose your question level", status_code=200)
def test_fetch_question(self):
request = HttpRequest()
request.method = "POST"
request.POST["level"] = "level"
request.POST["difficulty"] = "hard"
request.META["HTTP_HOST"] = "localhost"
response = views.process_question(request)
self.assertEqual(response.status_code, 200)
When using model
constructor, use keyword arguments! [1]
С помощью аргументов-ключей можно указать, каким аргументам вы присваиваете значение. Например:
Question(
type = content["type"],
difficulty = content["difficulty"],
category = content["category"],
question = content["question"],
correct_answer = content["correct_answer"],
incorrect_answers = content["incorrect_answers"]
)
Вы также можете использовать dict
распаковку для построения Question
. При этом аргументы будут получены автоматически:
Question(**question)
[1] In your example, the constructor of the class Question
takes question
which is a dict
and assigns this to its first argument id
.