我的模型具有良好的验证效果,我在模型中使用clean
方法。问题是当我验证我正在使用一个尚未在表单中设置的对象时,该对象引发了对象尚未存在的异常。
我想要一个解决方案在任何验证之前将对象从url主键传递给表单,所以我的clean方法工作正常。
这是一个类似的例子。
主要模型
class Student(models.Model):
first_name = models.CharField(max_length=30)
让我们坐下来,每个学生一次可能有一个学期。但是,如果之前有任何学期,则开始日期必须在最后一个学期结束日期之后。
class Semester(models.Model):
student = models.OneToOneField(Student)
start_date = models.DateField()
def clean(self):
# do not allow the start date to be before last semester end date
if self.student.semesterhistory_set.all().count() > 0:
last_semester_end_date = self.student.semesterhistory_set.last().end_date
if last_semester_end_date >= self.start_date:
message = _("Start Date for this semester must be after %s" % last_date)
raise ValidationError(message)
class SemesterHistory(models.Model):
student = models.ForeignKey(Student)
start_date = models.DateField()
end_date = models.DateField()
在视图中,我传递了在验证表单后将用于验证的学生对象。 (的问题)
# URL for this is like this student/(pk)/semesters/create/
class SemesterCreate(CreateView):
model = Semester
fields = ['start_date']
def form_valid(self, form):
form.instance.student = get_object_or_404(Student, id=int(self.kwargs['pk']))
return super(SemesterCreate, self).form_valid(form)
错误:
RelatedObjectDoesNotExist Semester has no student
答案 0 :(得分:0)
显然,您需要致电UserControl1
并返回Label
...语义错误的方法会在<form id="form1" runat="server">
<div>
<asp:textbox id="TextBox1" runat="server" width="100" cssclass="ddl_Class" validationgroup="First"></asp:textbox>
<asp:requiredfieldvalidator id="RequiredFieldValidator3" runat="server" controltovalidate="TextBox1"
errormessage="Error in TextBox1" text="***" display="None" validationgroup="First"></asp:requiredfieldvalidator>
<asp:regularexpressionvalidator id="RegularExpressionValidator4" runat="server" controltovalidate="TextBox1"
errormessage="TextBox1 only number" text="***" display="None" validationexpression="^\d+$" validationgroup="First"></asp:regularexpressionvalidator>
<asp:imagebutton id="btnSave1" runat="server" validationgroup="First" onclick="ButtonSave1_Click" imageurl="/Images/save_button.gif" onclientclick="if (!confirm('Confirm?')) return false;" />
<asp:textbox id="TextBox2" runat="server" width="100" cssclass="ddl_Class" validationgroup="Second"></asp:textbox>
<asp:requiredfieldvalidator id="RequiredFieldValidator4" runat="server" controltovalidate="TextBox2"
errormessage="Error " text="***" display="None" validationgroup="Second"></asp:requiredfieldvalidator>
<asp:imagebutton id="btnSave2" runat="server" validationgroup="Second" onclick="ButtonSave2_Click" imageurl="/Images/save_button.gif" onclientclick="if (!confirm('Confirm?')) return false;" />
</div>
<asp:validationsummary id="First" runat="Server" showmessagebox="true" cssclass="validation-summary-errors" />
<asp:validationsummary id="Second" runat="Server" showmessagebox="true" cssclass="validation-summary-errors" />
</form>
中提升 POST https://breatheimagevaultdev1.s3.amazonaws.com/ 403 (Forbidden
...
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Invalid according to Policy: Policy Condition failed: ["starts-with"
, "$key", "uploads/"]</Message><RequestId>3DCD6323247DF507</RequestId><HostId>x8HscPCt7rwDX+35AaPxbd
/H9ycBPjiewTni/CI3KBSnyqqn4rtzZAtlGCYUS5sEQs+shpuUen0=</HostId></Error>
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#the-save-method
答案 1 :(得分:0)
实际上要有一个干净的集我会添加一个自定义的ModelForm。我也使用CreateView,这就是我使用它的方式。
首先添加一个自定义ModelForm(我个人在我的应用程序中添加一个forms.py文件):
from django.contrib.auth.forms import UserCreationForm
from .model import Semester
class CreateSemesterForm(UserCreationForm):
error_messages = {
'last_date': _("some message"),
}
class Meta:
model = Semester
fields = ('some', 'fields') #or __all__
def clean_your_date_field(self):
#clean_name_field will be called when the form_valid will be called with all clean_fields functions
#here you define your clean method and raise Validation error
return field
def save(self, commit=True):
semester = super(CreateSemesterForm, self).save(commit=False)
#here you can set some other values
if commit:
semester.save()
return semester
在您的自定义CreateView中,您必须添加:
class SemesterCreate(CreateView):
form_class = CreateArtistForm
在ModelForm中设置模型和字段时,可以从CreateView中删除字段和模型args。
您还可以在Custom ModelForm中覆盖form_valid。
现在CreateView将调用form_valid来调用所有清理函数,如果它全部通过,它将返回并保存你的学期。
答案 2 :(得分:0)
我在面对与我的项目完全相同的问题后,昨天遇到了这个问题。
自从您发布此消息已经过了几年,但我想发布我的解决方案,以帮助其他可能偶然发现这一点的人。
我遇到的解决方案是使用自定义模型形式:
from django import forms
from .models import Blade
class SemesterForm(forms.ModelForm):
class Meta:
model = Semester
fields = '__all__'
widgets = {'student': forms.HiddenInput()}
在你看来:
class SemesterCreate(CreateView):
model = Semester
def get_initial(self, **kwargs):
# get current student from pk in url
current_student = get_object_or_404(Student,
pk=self.kwargs.get('pk'))
return { 'site': current_student }
这里的诀窍是你必须将学生字段设置为隐藏在表单中。这样,它将保留您在视图中提供的初始值,但不会对用户可用。
因此,当提交表单并调用full_clean()方法(然后将在模型上调用clean()方法)时,它将存在,并且在模型中执行了漂亮而整洁的验证clean()将工作。