我正在编写测试应用程序的问题,我正在编写以验证一些Django功能。测试应用程序是一个小型“成绩簿”应用程序,目前正在使用Alex Gaynor的只读字段功能http://lazypython.blogspot.com/2008/12/building-read-only-field-in-django.html
有两个可能相关的问题。首先,当我在下面的这两行中翻转评论时:
# myform = GradeForm(data=request.POST, instance=mygrade)
myform = GradeROForm(data=request.POST, instance=mygrade)
它的工作方式与我预期的一样,当然除了学生领域是可变的。
当评论以显示的方式显示时,“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
// 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())
// template
<p>{{ info }}</p>
<form method="POST" action="">
<table>
{{ myform.as_table }}
</table>
<input type="submit" value="Submit">
</form>
// 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
答案 0 :(得分: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
将它与CharField一起使用。
答案 1 :(得分:3)
Django 1.2(大约一周半前发布)支持开箱即用的管理员的只读字段:
我不确定将新功能扩展到您的网站上显示的ModelForm是多么困难,但它可以作为一个比Alex更新的起点(优秀但过时)代码。