保存后CharField值消失(只读字段)

时间:2010-05-31 17:42:18

标签: django django-models django-forms

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

以下是展示此问题的最简单示例。 (这是糟糕的数据库设计,我知道,我只提取了代码的相关部分来展示问题。在实际示例中, student 在自己的表中,但问题仍然存在于那里。)

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>

2 个答案:

答案 0 :(得分:1)

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

由于学生字段被禁用,表单提交将不会将其作为输入,因此显示验证错误消息的错误表单不会获得初始值。

这就是为什么ReadOnly 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

答案 1 :(得分:0)

我在这里伸展自己,所以有些想法:

%您是否​​嗅到了流量,以确切了解浏览器和服务器之间发送的内容?

%您是否​​需要将学生姓名作为隐藏字段发送(如果您不这样做,您的数据库更新可能会假设您希望学生空白)?

%你在Python解析之后看过HTML的来源了吗?