2010-05-31 34 views
0

我正在实施简单的“成绩簿”应用程序,其中教师可以更新成绩而不允许更改学生的姓名(至少不会更新年级页面)。为此,我使用了最简单的只读技巧之一。问题是,在SUBMIT后,视图重新显示为学生的'空白'值。我希望学生的名字重新出现。CharField值在保存后消失(只读字段)

下面是展示此问题的最简单示例。 (这是穷人DB设计,我知道,我刚提取的代码,展示问题的相关部分,在实际的例子,学生是在自己的表,但问题仍然存在那里。)

models.py

class Grade1(models.Model): 
    student = models.CharField(max_length=50, unique=True) 
    finalGrade = models.CharField(max_length=3) 

class Grade1OForm(ModelForm): 
    student = forms.CharField(max_length=50, required=False) 
    def __init__(self, *args, **kwargs): 
     super(Grade1OForm,self).__init__(*args, **kwargs) 
     instance = getattr(self, 'instance', None) 
     if instance and instance.id: 
      self.fields['student'].widget.attrs['readonly'] = True 
      self.fields['student'].widget.attrs['disabled'] = 'disabled' 
    def clean_student(self): 
     instance = getattr(self,'instance',None) 
     if instance: 
      return instance.student 
     else: 
      return self.cleaned_data.get('student',None) 
    class Meta: 
     model=Grade1 

views.py

from django.forms.models import modelformset_factory 
def modifyAllGrades1(request): 
    gradeFormSetFactory = modelformset_factory(Grade1, form=Grade1OForm, extra=0) 
    studentQueryset = Grade1.objects.all() 
    if request.method=='POST': 
     myGradeFormSet = gradeFormSetFactory(request.POST, queryset=studentQueryset) 
     if myGradeFormSet.is_valid(): 
      myGradeFormSet.save() 
      info = "successfully modified" 
    else: 
     myGradeFormSet = gradeFormSetFactory(queryset=studentQueryset) 
    return render_to_response('grades/modifyAllGrades.html',locals()) 

模板

<p>{{ info }}</p> 
<form method="POST" action=""> 
<table> 
{{ myGradeFormSet.management_form }} 
{% for myform in myGradeFormSet.forms %} 
    {# myform.as_table #} 
    <tr> 
    {% for field in myform %} 
    <td> {{ field }} {{ field.errors }} </td> 
    {% endfor %} 
    </tr> 
{% endfor %} 
</table> 
<input type="submit" value="Submit"> 
</form> 

回答

1

你显示只读字段的方式是问题。

由于学生字段被禁用,表单提交不会再有这样的投入,使显示与验证错误消息没有得到初始值的误差形式。

这就是为什么只读的Widget必须比只是作为一个HTML无效字段更加复杂。

尝试使用真正的ReadOnlyWidget,一个覆盖_has_changed

以下是我使用的。对于实例化,如果它不同,它将采用original_value和可选的display_value。

class ReadOnlyWidget(forms.Widget): 

    def __init__(self, original_value, display_value=None): 
     self.original_value = original_value 
     if display_value: 
      self.display_value = display_value 
     super(ReadOnlyWidget, self).__init__() 

    def _has_changed(self, initial, data): 
     return False 

    def render(self, name, value, attrs=None): 
     if self.display_value is not None: 
      return unicode(self.display_value) 
     return unicode(self.original_value) 

    def value_from_datadict(self, data, files, name): 
     return self.original_value 
+0

谢谢Lakshman,但我还是Django的新手。我如何设置原始值?我试图把它叫做:student = forms.CharField(max_length = 50,widget = ReadOnlyWidget())但这不对,因为我需要传入一个原始值。注意...我最终的目标是在模型表单中使用它。 – jamida 2010-05-31 21:21:05

+0

jamida:传递给ReadOnlyWidget,一个学生实例,您想要在窗体上只读显示。 – 2010-05-31 21:46:06

+0

如何在modelformset中做到这一点?我是否在上面的代码示例或表单的__init__例程中执行此操作? (或者?)并且如果init例程,我该如何引用该init例程中的小部件?注意。我很乐意阅读文档,但深入django并没有很好的文档。如果你有链接,那会很棒! – jamida 2010-05-31 22:09:18

0

我在这里稍微拉伸自己,所以有些想法:

%您是否嗅探过流量以确切地查看浏览器和服务器之间发送的内容?

%你需要发送的学生姓名作为隐藏字段(你的数据库更新的东西可以假设你想学生空白,如果你不这样做)?

%在Python解析它之后,您看过了HTML的源代码吗?

+0

感谢您试用巴里......一些相关的评论。一个是另一个只读技巧工作得很好。但是,如果学生字段是另一个表(我的完整应用程序)中的外键,那么这个技巧将不起作用。另一个是,我查看了生成的HTML和POST变量。 Django没有让学生回来,这对DISABLED和/或READONLY字段是正常的。由于CLEAN例程将其设置为正确的值,所以不成问题。最后,我在clean例程的else子句中放置了一个print语句,但没有被调用。所以学生总是可用的。 – jamida 2010-05-31 19:15:11