Django Form中的奇怪行为(只读字段/小部件)

jam*_*ida 4 django django-models django-forms

我正在编写测试应用程序的问题,我正在编写以验证一些Django功能.测试应用程序是一个小型的"等级书"应用程序,目前正在使用Alex Gaynor的只读字段功能http://lazypython.blogspot.com/2008/12/building-read-only-field-in-django.html

有两个问题可能是相关的.首先,当我在下面的这2行中翻转评论时:

#        myform = GradeForm(data=request.POST, instance=mygrade)
        myform = GradeROForm(data=request.POST, instance=mygrade)
Run Code Online (Sandbox Code Playgroud)

它的工作方式与我预期的一样,当然除了学生领域是可变的.

当评论以显示的方式显示时,"studentId"字段显示为数字(不是名称,问题1),当我点击提交时,我收到一条错误,指出studentId需要是Student实例.

我不知道如何解决这个问题.我并不喜欢Alex Gaynor的代码.任何代码都可以.我对Python和Django都比较陌生,所以我在网站上看到的"让一个只读字段变得容易"的提示仍然超出我的范围.

// models.py

class Student(models.Model):
    name = models.CharField(max_length=50)
    parent = models.CharField(max_length=50)
    def __unicode__(self):
        return self.name

class Grade(models.Model):
    studentId = models.ForeignKey(Student)
    finalGrade = models.CharField(max_length=3)

# testbed.grades.readonly is alex gaynor's code
from testbed.grades.readonly import ReadOnlyField
class GradeROForm(ModelForm):
    studentId = ReadOnlyField()
    class Meta:
        model=Grade

class GradeForm(ModelForm):
    class Meta:
        model=Grade
Run Code Online (Sandbox Code Playgroud)

// views.py

def modifyGrade(request,student):
    student = Student.objects.get(name=student)
    mygrade = Grade.objects.get(studentId=student)
    if request.method == "POST":
#        myform = GradeForm(data=request.POST, instance=mygrade)
        myform = GradeROForm(data=request.POST, instance=mygrade)
        if myform.is_valid():
            grade = myform.save()
            info = "successfully updated %s" % grade.studentId
    else:
#        myform=GradeForm(instance=mygrade)
        myform=GradeROForm(instance=mygrade)
    return render_to_response('grades/modifyGrade.html',locals())
Run Code Online (Sandbox Code Playgroud)

//模板

<p>{{ info }}</p>
<form method="POST" action="">
<table>
{{ myform.as_table }}
</table>
<input type="submit" value="Submit">
</form>
Run Code Online (Sandbox Code Playgroud)

// Alex Gaynor的代码

from django import forms
from django.utils.html import escape
from django.utils.safestring import mark_safe

from django.forms.util import flatatt
class ReadOnlyWidget(forms.Widget):
    def render(self, name, value, attrs):
        final_attrs = self.build_attrs(attrs, name=name)
        if hasattr(self, 'initial'):
            value = self.initial
        return mark_safe("<span %s>%s</span>" % (flatatt(final_attrs), escape(value) or ''))

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

class ReadOnlyField(forms.FileField):
    widget = ReadOnlyWidget
    def __init__(self, widget=None, label=None, initial=None, help_text=None):
        forms.Field.__init__(self, label=label, initial=initial, 
            help_text=help_text, widget=widget)

    def clean(self, value, initial):
        self.widget.initial = initial
        return initial
Run Code Online (Sandbox Code Playgroud)

Lak*_*sad 5

不要打扰ReadOnlyField.请改用Widget.

这是我经常使用的那个.

class ReadOnlyWidget(forms.Widget):

    def __init__(self, original_value, display_value):
        self.original_value = original_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
Run Code Online (Sandbox Code Playgroud)

与CharField一起使用.