在CreateView form_valid方法

时间:2015-07-22 03:42:54

标签: python django django-models

我的模型具有良好的验证效果,我在模型中使用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

3 个答案:

答案 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()将工作。