我正在尝试使用ModelForms,但实际上我似乎正在用餐。 这些模型是“答案”中的各种子类。
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
ordering = ['user']
class Brainstorm(Answer):
brain_bolt = models.CharField(max_length=200, default="")
responds_to = models.ForeignKey('self', models.SET_NULL, blank=True, null=True)
class Meta:
ordering = ['-pk', ]
ModelForms都遵循这种模式:
class BrainstormForm(ModelForm):
class Meta:
model = Brainstorm
fields = '__all__'
问题模型中定义了三种可能的答案模式:
MULTIPLE_ENTRY_OPTIONS = (
('S', 'Single Entry'), # single pk. User changes are final.
('T', 'Change-Tracked Single Entry'), # multiple-pks, but only the most recent is presented to the user
('M', 'Many answer instances are valid'), # question requires many answers - suitable for brainstorming
)
页面可能包含多个具有不同答案类型和形式的问题,因此,我不使用表单集,而是使用问题主键和答案主键的前缀字符串分别区分它们,然后可以再次将其解压缩获取问题和答案对象。
我对每个页面有两个基于功能的视图:page_view(响应获取)和answer(响应POST)。 Page_view创建并填写新表单以呈现给用户。答案应该通过保存返回的数据来响应POST请求。可能会将其保存为新条目或将其保存为修订。
def answer(request, project_id, user_id, next_question_page):
"""
answer handles getting submitted answers from http request objects into the
database, using either the 'answer-value' path (without Django Forms) or the "q-"
path, which uses form instantiator to unpack the form.
"""
# attempt to standardise saving of answers (votes, shorts, longs, E3, vE4 etc)
user = User.objects.get(username=user_id)
next_page = 'not_set'
for key, value in request.POST.items():
if key.startswith("q"):
q_number = re.search(r'q(\d+)#(\d+).+', key)
pk_q = int(q_number.group(1)) # the digits are the question primary key
pk_ans = int(q_number.group(2)) # these digits are the pk of the answer
prefix = prefix = "q" + str(pk_q) + '#' + str(pk_ans)
question = Question.objects.get(pk=pk_q)
answer_class = ANSWER_CLASS_DICT[question.answer_type]
model_instance = answer_class.objects.get(pk=pk_ans)
form_instance = form_instantiator(question, request, instance=model_instance, prefix=prefix)
print(form_instance)
print(form_instance.fields('question'))
if form_instance.is_valid:
form_instance.save()
if question.answer_type == 'BS':
return HttpResponseRedirect(reverse('polls:project:page', args=(
project_id,
user_id,
question.man_page)))
elif request and instance:
form = FORM_CLASSES[question.answer_type](request.POST, prefix=prefix)
form.fields['user'] = user
form.fields['question'] = question
temp_answer = form.save(commit=False)
temp_answer.question = question
temp_answer.user = user
print('temp_answer:', temp_answer.question, temp_answer.user, temp_answer.brain_bolt)
else:
form = FORM_CLASSES[question.answer_type]()
return form
错误是“ form.save(commit = False)失败,因为表单未通过验证。”我很困惑,因为在阅读了此(docs)之后,我相信commit = False将使我创建一个不完整的Answer对象,可以进一步填充然后保存。
我为这个巨大的问题表示歉意。很高兴得到“您不能从这里到达那里”的答案。
请求方法:POST请求URL:http://127.0.0.1:8000/polls/p1/cruicksa/pg11/ans
Django版本:1.11.4 Python版本:3.6.0已安装的应用程序: ['polls.apps.PollsConfig','django.contrib.admin', 'django.contrib.auth','django.contrib.contenttypes', 'django.contrib.sessions','django.contrib.messages', 'django.contrib.staticfiles','import_export']已安装的中间件: ['django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware']
跟踪:
文件 “ C:\ Users \ cruicksa \ AppData \ Local \ Continuum \ Anaconda3 \ lib \ site-packages \ django \ core \ handlers \ exception.py” 在内部 41. response = get_response(request)
文件 “ C:\ Users \ cruicksa \ AppData \ Local \ Continuum \ Anaconda3 \ lib \ site-packages \ django \ core \ handlers \ base.py” 在_get_response中 187. response = self.process_exception_by_middleware(e,request)
文件 “ C:\ Users \ cruicksa \ AppData \ Local \ Continuum \ Anaconda3 \ lib \ site-packages \ django \ core \ handlers \ base.py” 在_get_response中 185. response = wrapd_callback(request,* callback_args,** callback_kwargs)
文件 “ C:\ Users \ cruicksa \ AppData \ Local \ Continuum \ Anaconda3 \ lib \ site-packages \ django \ contrib \ auth \ decorators.py” 在_wrapped_view中 23. return view_func(request,* args,** kwargs)
文件“ H:\ Workspace \ Django_Code \ Acejet_development \ polls \ views.py”在 回答 164. form_instance = form_instantiator(问题,请求,实例= model_instance,前缀=前缀)
文件“ H:\ Workspace \ Django_Code \ Acejet_development \ polls \ forms.py”在 form_instantiator 191. temp_answer = form.save(commit = False)
文件 “ C:\ Users \ cruicksa \ AppData \ Local \ Continuum \ Anaconda3 \ lib \ site-packages \ django \ forms \ models.py” 在保存 458.如果self.instance._state。添加了其他“ changed”,则“创建”,
异常类型:/ polls / p1 / cruicksa / pg11 / ans处的ValueError异常 价值:因为没有数据,所以无法创建“头脑风暴” 验证。
答案 0 :(得分:0)
is_valid
是可调用的,因此应该是
if form_instance.is_valid():
您错过了()
。
答案 1 :(得分:0)
发布长问题的问题在于,很难看到问题从何而来。
我使用的是模型形式,但是应该排除几个字段-例如,用户,因为: 一种。用户不应代表他人回答,并且 b。该应用程序不应在每次页面加载时向每个用户发送完整的用户列表。
我的设计问题是接收其他字段的用户输入,并在调用验证之前将“问题”和“用户”数据添加回表单。我也有相当一部分代码可以工作,但是需要进行更改,以便我可以正确使用“表单”(我正在创建答案,将其加载到表单中,发送给用户,然后希望有时(而不是其他时间)再次与它们匹配)。
从this answer开始工作,现在我的应用可以再次工作并正确使用表单。
我迁移了“页面”和“答案”的视图以获取和发布基于类的视图,并用form_getter和form_post函数替换了form_instantiator。
我必须学习的是如何填充数据字典以用于创建表单。
@method_decorator(login_required)
def post(self, request, project_id, page_num):
self.user = User.objects.get(username=request.user.username)
self.next_page = 'not_set'
self.form_items = {}
prefixes = []
for key, value in request.POST.items():
if key.startswith("q"):
q_number = re.search(r'q(\d+)#', key)
pk_q = int(q_number.group(1)) # the digits are the question primary key
prefix = 'q' + str(pk_q) + '#'
if prefix not in prefixes:
prefixes.append(prefix)
self.form_items[prefix] = {key: value for key, value in request.POST.items() if prefix in key}
# https: // stackoverflow.com / questions / 45441048 / how - do - i - filter - a - dictionary - based - on - the - partial - string - matches
question = Question.objects.get(pk=pk_q)
self.form_items[prefix].update({(prefix + '-question'): question.pk,
(prefix +'-user'): self.user.pk})
form = form_post(value=self.form_items[prefix], question=question, user=self.user)
form.save()
这仍然让人有点,取决于将前缀添加到数据字段名称的硬编码版本(“ -question”)中。这是必要的,因为我在单个“提交”中包装了几种可能相同类型的表格。另外,流经过request.POST分为两个循环(一个循环是单行理解),这很浪费。
但是随着问题和用户的添加,现在可以创建和保存有效的表格。感谢所有尝试提供帮助的人。
在有form.fields ['question'] =问题的地方,我应该一直在编辑请求。将输入后的POST输入到正确的完整数据集中。