Django 表单缺少一个字段

Posted

技术标签:

【中文标题】Django 表单缺少一个字段【英文标题】:Django form missing a field 【发布时间】:2011-08-03 23:06:32 【问题描述】:

我有一个模型和一个模型表单来更改一些设置。表单显示正常,值正确,但是当我提交表单时,request.POST dict中缺少一个字段。

型号:

class NodeSettings(models.Model):
    nodetype = models.CharField(max_length=8, editable=False)
    nodeserial = models.IntegerField(editable=False)
    upper_limit = models.FloatField(null=True, blank=True,
                                    help_text="Values above this limit will be of different color.")
    graph_time = models.IntegerField(null=True, blank=True,
                                     help_text="The `width' of the graph, in minutes.")
    tick_time = models.IntegerField(null=True, blank=True,
                                    help_text="Number of minutes between `ticks' in the graph.")
    graph_height = models.IntegerField(null=True, blank=True,
                                       help_text="The top value of the graphs Y-axis.")

    class Meta:
        unique_together = ("nodetype", "nodeserial")

视图类(我使用 Django 1.3 和基于类的视图):

class EditNodeView(TemplateView):
    template_name = 'live/editnode.html'

    class NodeSettingsForm(forms.ModelForm):
        class Meta:
            model = NodeSettings

    # Some stuff cut out

    def post(self, request, *args, **kwargs):
        nodetype = request.POST['nodetype']
        nodeserial = request.POST['nodeserial']

        # 'logger' is a Django logger instance defined in the settings
        logger.debug('nodetype   = %r' % nodetype)
        logger.debug('nodeserial = %r' % nodeserial)

        try:
            instance = NodeSettings.objects.get(nodetype=nodetype, nodeserial=nodeserial)
            logger.debug('have existing instance')
        except NodeSettings.DoesNotExist:
            instance = NodeSettings(nodetype=nodetype, nodeserial=nodeserial)
            logger.debug('creating new instance')

        logger.debug('instance.tick_time = %r' % instance.tick_time)

        try:
            logger.debug('POST[tick_time] = %r' % request.POST['tick_time'])
        except Exception, e:
            logger.debug('error: %r' % e)

        form = EditNodeView.NodeSettingsForm(request.POST, instance=instance)
        if form.is_valid():
            from django.http import HttpResponse
            form.save()
            return HttpResponse()
        else:
            return super(EditNodeView, self).get(request, *args, **kwargs)

模板的相关部分:

<form action=" url edit_node/" method="POST">
  % csrf_token %
  <table>
     form.as_table 
  </table>
  <input type="submit" value="Ok" />
</form>

这是运行调试服务器时控制台中的调试输出:

2011-04-12 16:18:05,972 DEBUG nodetype   = u'V10'
2011-04-12 16:18:05,972 DEBUG nodeserial = u'4711'
2011-04-12 16:18:06,038 DEBUG have existing instance
2011-04-12 16:18:06,038 DEBUG instance.tick_time = 5
2011-04-12 16:18:06,039 DEBUG error: MultiValueDictKeyError("Key 'tick_time' not found in <QueryDict: u'nodetype': [u'V10'], u'graph_time': [u'5'], u'upper_limit': [u''], u'nodeserial': [u'4711'], u'csrfmiddlewaretoken': [u'fb11c9660ed5f51bcf0fa39f71e01c92'], u'graph_height': [u'25']>",)

如您所见,字段 tick_time 不在 request.POST 的 QueryDict 中。

需要注意的是,该字段位于网络浏览器中,在查看 HTML 源代码时,它看起来就像表单中的其他字段。

任何人对可能出现的问题有任何提示吗?

【问题讨论】:

【参考方案1】:

由于您使用的是通用视图,最好扩展ProcessFormView而不是TemplateView

编辑

我已经用TemplateView 试过你的代码:

class EditNodeView(TemplateView):

您有get_context_data 来推送表单吗?

def get_context_data(self, **kwargs):
    instance = NodeSettings.objects.get(pk=kwargs['node_id'])
    form = EditNodeView.NodeSettingsForm(instance=instance)
    context = super(EditNodeView, self).get_context_data(**kwargs)
    context['form'] = form
    return context

编辑现有对象的最佳方法是通过主键获取,我在urls.py中有以下内容:

url(r'^edit-node/(?P<node_id>\d+)/$', EditNodeView.as_view(), name='edit-node'),

我通过主键获取实例,可能想要在上面进行一些检查,例如如果不存在则抛出 404。

在您的模型中,您有nodetypenodeserial 作为editable=False,如果它们设置为不可编辑,您如何显示或创建这些项目?出于测试目的,我已将它们设置为 True

在模板中,我将第一行改为:

<form action="" method="POST">

我知道有很多变化,但以上可以正确查看和编辑您的模型。您可以在表单级别将nodetypenodeserial 设置为只读,以防止人们对其进行编辑。

【讨论】:

转换为使用 FormView 而不是 TemplateView,但基本问题仍然是 request.POST 缺少 'tick_time' 字段。 优先级已更改,因此暂时搁置,但我会在一两周内仔细查看您的答案。

以上是关于Django 表单缺少一个字段的主要内容,如果未能解决你的问题,请参考以下文章

表单字段的 Django 跳过选项

即使缺少所需的值,Django 验证也会调用 clean()

带有复选框的表单输入字段,反之亦然 - 缺少第一个值

Django 向导表单中的条件表单字段

Django:form.is_valid 检查后,cleaned_data 缺少图像字段

Django 表单:提交表单时出现隐藏字段错误