Я выполнил это двумя способами: один из них включает запись в файл, а другой - запись в модель.Поскольку запись в модели, очевидно, быстрее, я продемонстрирую, что:
На мой взгляд, это довольно просто.Здесь начало этого заключается в том, что я передаю словарь слов в форму, когда создаю экземпляр формы по запросу GET
form = TestForm(wordsdict)
.Данные POST-запроса фактически никогда не хранятся, они просто используются для проверки.Поэтому, когда я POST, я просто отправляю данные POST, как обычно.wordsdict
- это словарь, состоящий из {answer: [question, id]}
views.py
def language_test(request, username='johndoe', password=None):
lang= Language(config('USER'), config('PASS'))
streakinfo = lang.get_streak_info()
context = {
'username': username,
'streakinfo': streakinfo,
}
template_name = 'tests/test.html'
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the saved answer dictionary:
print('POSTING TEST RESULTS')
form = TestForm(data=request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
print('PASSED')
# redirect to a new URL:
return redirect('main:success')
else:
print('FAILED')
if form.has_error:
print('FORM ERROR')
pass
# if a GET (or any other method) we'll create a blank form
else:
print('GETTING NEW TEST')
phrases = lang.get_known_phrases()
testwords = get_test_words(phrases)
wordsdict = get_word_dict(testwords)
form = TestForm(wordsdict)
context['form'] = form
return render(request, template_name, context)
Снова прямо вперед ...
models.py
class TestAnswers(models.Model):
phraseid = models.IntegerField(unique=True, blank=True, null=True)
question = models.TextField(blank=True, null=True)
answer = models.CharField(max_length=50, blank=True, null=True)
Здесь происходит волшебство.Я управляю функцией __init__
унаследованного класса Form
.Когда создается экземпляр класса, он оценивает аргумент test_dict
, который может быть передан или не передан представлением.Если нет test_dict
, это должен быть запрос на новый тест, поэтому я очищаю тестовую модель и создаю новую со случайно выбранными вопросами \ ответами, передаваемыми представлением.Если не передано test_dict
, то это должен быть почтовый запрос, то есть мне нужно проверить все ответы.Обратитесь к чистому методу для проверки формы.
forms.py
class TestForm(forms.Form):
"""
Student test form
"""
def __init__(self, test_dict=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self._resource_path = os.path.join(settings.BASE_DIR, 'static/json')
self._json_path = os.path.join(self._resource_path, 'answers.json')
self._model = TestAnswers
i = 0
phraseid, answer, question = [], [], []
if test_dict is not None:
# A form get request should resolve new form data and
# store it in the database for comparison later on
# clear out the answers table
self._model.objects.all().delete()
# create a list of model objects to bulk insert
records = []
for item in test_dict:
record = self._model(
phraseid=test_dict[item]['id'],
answer=item,
question=test_dict[item]['definition']
)
phraseid.append(test_dict[item]['id'])
question.append(test_dict[item]['definition'])
answer.append(item)
records.append(record)
if records:
# Insert the records into the TestAnswers table
self._model.objects.bulk_create(records)
self.test_dict = test_dict
else:
# A form post request should check the form data against
# what was established during the get request
# Get all the objects in the test table
records = self._model.objects.all()
# Put all the object items into their respective lists
for r in records:
phraseid.append(r.phraseid)
answer.append(r.answer)
question.append(r.question)
for i in range(len(question)):
# Set the form fields
field_name = 'testword' + str(phraseid[i])
# Print the answers for debugging
print('id: ' + str(phraseid[i]))
print('question: ' + question[i])
print('answer:' + answer[i])
self.fields[field_name] = forms.CharField(label=question[i], max_length=100)
self.question = question
self.phraseid = phraseid
self.answer = answer
def clean(self):
# print('CLEANING DATA')
phraseid, answer, question = [], [], []
context = {}
i = 0
records = self._model.objects.all()
for r in records:
phraseid.append(r.phraseid)
answer.append(r.answer)
question.append(r.question)
# Get and check the results
for i in range(len(self.cleaned_data)):
field_name = 'testword' + str(phraseid[i])
result = self.cleaned_data.get(field_name)
if result != answer[i]:
self.add_error(field_name, 'Incorrect')
context[i] = question[i]
i += 1
return context