我现在可以工作了!我想我会提出这个工作代码,以防有人发现它有用。可能使这变得有趣的困难来源之一是,我仅将表单用于多字段答案,而不将它们用于单字段答案。任何对此的评论都将受到欢迎。我对此很陌生。
models.py
class Question(models.Model):
...
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE, default = 1)
class Meta:
abstract = True
# What follows is a class method that gets existing answers, creates new default entries or updates answers depending on when it is called. It assumes that each question is answered only once.
@classmethod
def get_or_update_answer(self, user, question, submitted_value={None}):
if question.answer_type == 'CH':
if submitted_value == {None}:
selected_choice = question.choice_set.first() # by default, select the top of a set of radio buttons
answer, _created = Vote.objects.get_or_create(user = user, question = question, defaults={'choice':selected_choice})
else:
selected_choice = question.choice_set.get(pk=submitted_value)
answer = Vote.objects.get(user = user, question = question)
answer.choice = selected_choice
if question.answer_type == 'SA':
if submitted_value == {None}:
submitted_value = "brief response"
answer, _created = Short_Answer.objects.get_or_create(user = user, question = question, defaults={'short_answer': submitted_value})
else:
answer = Short_Answer.objects.get(user = user, question = question)
answer.short_answer = submitted_value
if question.answer_type == 'LA':
if submitted_value == {None}:
submitted_value = "full response"
answer, _created = Long_Answer.objects.get_or_create(user = user, question = question, defaults={'long_answer':submitted_value})
else:
answer = Long_Answer.objects.get(user = user, question = question)
answer.long_answer = submitted_value
if question.answer_type == 'E3':
if submitted_value == {None}:
submitted_value = {'lowest_value': 0, 'lv_rationale': "low estimate reasons",
'highest_value':0, 'hv_rationale': "high estimate reasons",
'best_value':0, 'bv_rationale': "best estimate reasons",}
answer, _created = EJ_three_field.objects.get_or_create(user= user, question = question, defaults=submitted_value)
else:
answer = EJ_three_field.objects.get(user= user, question = question)
for key, value in submitted_value.items():
setattr(answer,key,value)
if question.answer_type == 'E4':
if submitted_value == {None}:
submitted_value = {'lowest_value': 0, 'lv_rationale': "low estimate reasons",
'highest_value':0, 'hv_rationale': "high estimate reasons",
'best_value':0, 'bv_rationale': "best estimate reasons",
'confidence': 0, 'conf_rationale': "reasons for confidence score",}
answer, _created = EJ_four_field.objects.get_or_create(user = user, question = question, defaults=submitted_value)
else:
answer = EJ_four_field.objects.get(user= user, question = question)
for key, value in submitted_value.items():
setattr(answer,key,value)
# answer.save() - not required for create / update funcs
answer.save()
return answer
class Short_Answer(Answer):
class Long_Answer(Answer):
class Vote(Answer):
class EJ_three_field(Answer):
class EJ_four_field(Answer):
Views.py
def pageView(request, user_id, page_num):
question_set = Question.objects.filter(man_page = page_num)
user = User.objects.get(username = user_id)
template = 'polls/page_question.html'
context = {'question_set' : question_set, }
forms = {}
answers = {}
for question in question_set:
answers[question] = Answer.get_or_update_answer(user, question)
form_instance = form_instantiator(question, instance = answers[question])
forms[question] = form_instance
context['forms']=forms
context['answers']=answers
return render(request, template, context)
@login_required
def answer(request, user_id, man_index):
#attempt to standardise saving of answers (votes, shorts, longs, E3, vE4 etc)
user = User.objects.get(username = user_id)
question = Question.objects.get(man_index = man_index)
form_instance = form_instantiator(question, request = request)
if form_instance == None:
answer_value = request.POST['answer_value']
Answer.get_or_update_answer(user = user, question = question, submitted_value = answer_value)
else:
form = form_instantiator(question, request = request)
if form.is_valid():
print(form.cleaned_data)
Answer.get_or_update_answer(user = user, question = question, submitted_value = form.cleaned_data)
return HttpResponseRedirect(reverse('polls:page', args=(user_id, question.man_page)))
回答我最初的问题:可以使用 (instance=) 或 (request.POST) 或未绑定创建 ModelForm,两者都不绑定。提交数据时,会丢弃与上下文一起传递的对象。一个ModelForm可以用form.save()保存,效率很高。