Reputation: 409146
I have a model and a modelform to change some settings. The form is displayed allright, with the correct values, but when I submit the form one field is missing in the request.POST dict.
The model:
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")
The view class (I'm using Django 1.3 with class-based views):
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)
The relevant portion of the template:
<form action="{{ url }}edit_node/" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Ok" />
</form>
Here is the debug output in the console when running the debug server:
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']}>",)
As you can see, the field tick_time is nowhere in the QueryDict from request.POST.
It should be noted that the field is in the web-browser, and when looking at the HTML source it looks just like the other fields in the form.
Anyone have any hints on what can be wrong?
Upvotes: 0
Views: 2766
Reputation: 46264
Since you are using generic view, isn't it best to extend ProcessFormView instead of TemplateView
?
EDIT
I've tried your code with TemplateView
:
class EditNodeView(TemplateView):
Do you have a get_context_data
to push the form?
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
The best way for editing existing objects is to get by primary key, I have the following in the urls.py
:
url(r'^edit-node/(?P<node_id>\d+)/$', EditNodeView.as_view(), name='edit-node'),
I fetch the instance by primary key, might want to do some checking above like throwing 404 if not present.
In your models, you have nodetype
and nodeserial
as editable=False
, how do you display or create those items if they are set to not editable? I've set them to True
for testing purposes.
In the template, I have changed the first line to:
<form action="" method="POST">
I'm aware that there are a lot of changes but the above can view and edit your model properly. You could set the nodetype
and nodeserial
to be read-only at the form level to prevent people from editing it.
Upvotes: 1