2016-08-09 19 views
0

我有两个从单个视图提交的模型表单。一个模型是另一个的ForeignKey。此时,表单将添加到数据库,但并不如预期。我没有添加课程和部分(课程字段填充了新创建的课程),而是获取了已链接的课程和部分,但使用作为课程名称和部分名称输入的部分名称。多个表单提交单个视图 - Django

models.py

class Course(models.Model): 
    Name = models.CharField(max_length=30,unique=True) 
    Active = models.BooleanField(default=True) 

    def __unicode__(self): 
     return u'%s' % (self.Name) 

class Section(models.Model): 
    Name = models.CharField(max_length=30,default='.',unique=True) 
    course = models.ForeignKey(Course, on_delete=models.CASCADE) 
    assessments = models.ManyToManyField(Assessment) 

    def __unicode__(self): 
     return u'%s/%s' % (self.Name, self.course) 

forms.py

class CourseAddForm(forms.ModelForm): 
    class Meta: 
     model = Course 
     fields = ['Name', 'Active'] 
class SectionAddForm(forms.ModelForm): 
    class Meta: 
     model = Section 
     fields = ['Name'] 

模板/ index.html中

<!-- COURSE ADD MODAL --> 
<div class="modal fade" id="CourseAddModal" role="dialog"> 
<div class="modal-dialog"> 

    <!-- Modal content--> 
    <div class="modal-content"> 
    <div class="modal-header" style="padding:5px 10px;"> 
     <button type="button" class="close" data-dismiss="modal">&times;</button> 
     <h4>Add Course</h4> 
    </div> 
    <div class="modal-body" style="padding:10px 10px;"> 
     <form data-parsley-validate method="post" id="coursesecaddform" action="" enctype="multipart/form-data" 
       data-parsley-trigger="focusout"> 

     {% csrf_token %} 
     Add course 
     {{ courseaddform.as_p }} 
     Add section 
     {{ sectionaddform.as_p }} 

     <p id="login-error"></p> 

     <input type="submit" class="btn btn-info submit" name="AddCourse" value="Add Course" /> 
     </form> 
    </div> 
    <div class="modal-footer"> 
    </div> 
    </div> 

</div> 
</div> 

views.py

def IndexView(request,Course_id,Section_id): 
    if request.method == "GET": 

     this_course = Course.objects.get(pk=Course_id) 
     active_courses = Course.objects.all().filter(Active=True).exclude(pk=Course_id) 
     section_list = Section.objects.all().filter(course=this_course) 
     if len(section_list) >1: 
      multi_section = True 
     else: 
      multi_section = False 
     active_section = Section.objects.get(pk=Section_id) 
     roster = Student.objects.all().filter(sections__in=[active_section]) 
     announcement_list = Announcement.objects.all().filter(sections__in=[active_section]) 
     courseaddform = CourseAddForm() 
     sectionaddform = SectionAddForm() 

     context = {'active_courses':active_courses, 'this_course': this_course, 
        'active_section':active_section, 'section_list':section_list, 
        'roster':roster, 'multi_section':multi_section, 
        'announcement_list':announcement_list, 'courseaddform':courseaddform, 
        'sectionaddform':sectionaddform} 
     return render(request,'gbook/index.html', context) 
    elif request.method == "POST": 
     this_course = Course.objects.get(pk=Course_id) 
     active_courses = Course.objects.all().filter(Active=True).exclude(pk=Course_id) 
     section_list = Section.objects.all().filter(course=this_course) 
     if len(section_list) >1: 
      multi_section = True 
     else: 
      multi_section = False 
     active_section = Section.objects.get(pk=Section_id) 

     f = CourseAddForm(request.POST, instance=Course()) 
     g = SectionAddForm(request.POST, instance=Section()) 
     if f.is_valid() and g.is_valid(): 
      new_course = f.save() 
      new_section = g.save(commit=False) 
      new_section.course = new_course 
      print new_section.course 
      new_section.save() 

     return redirect("/gbook/"+str(Course_id)+"/"+str(active_section)) 

回答

1

解决方案:

代替使用instance说法,使用prefix

def IndexView(request,Course_id,Section_id): 
    if request.method == "GET": 

     this_course = Course.objects.get(pk=Course_id) 
     active_courses = Course.objects.all().filter(Active=True).exclude(pk=Course_id) 
     section_list = Section.objects.all().filter(course=this_course) 
     if len(section_list) >1: 
      multi_section = True 
     else: 
      multi_section = False 
     active_section = Section.objects.get(pk=Section_id) 
     roster = Student.objects.all().filter(sections__in=[active_section]) 
     announcement_list = Announcement.objects.all().filter(sections__in=[active_section]) 
     courseaddform = CourseAddForm(prefix='crs') 
     sectionaddform = SectionAddForm(prefix='sctn') 

     context = {'active_courses':active_courses, 'this_course': this_course, 
        'active_section':active_section, 'section_list':section_list, 
        'roster':roster, 'multi_section':multi_section, 
        'announcement_list':announcement_list, 'courseaddform':courseaddform, 
        'sectionaddform':sectionaddform} 
     return render(request,'gbook/index.html', context) 
    elif request.method == "POST": 
     this_course = Course.objects.get(pk=Course_id) 
     active_courses = Course.objects.all().filter(Active=True).exclude(pk=Course_id) 
     section_list = Section.objects.all().filter(course=this_course) 
     if len(section_list) >1: 
      multi_section = True 
     else: 
      multi_section = False 
     active_section = Section.objects.get(pk=Section_id) 

     f = CourseAddForm(request.POST, prefix='crs') 
     g = SectionAddForm(request.POST, prefix='sctn') 
     if f.is_valid() and g.is_valid(): 
      new_course = f.save() 
      new_section = g.save(commit=False) 
      new_section.course = new_course 
      print new_section.course 
      new_section.save() 

     return redirect("/gbook/"+str(Course_id)+"/"+str(active_section)) 
+0

为了清楚起见,'instance'允许你预先填充一个带有数据的表单和/或编辑一个现有的模型实例。 'prefix'在生成的表单域的名称和ID属性上添加一个唯一的前缀,这可能是解决问题的理想方法。这不是真正的“实例”或“前缀”选择,因为它们做了不同的事情,甚至可以同时使用。再说一遍,我认为使用'prefix'在这里是正确的。 – souldeux

+0

谢谢你的背景!这非常有帮助。 – DeltaG

0

两种型号具有Name场,所以这两种形式包含具有相同属性name的输入。当Django遇到两个具有相同名称的POST参数时,它将通过该名称将最后一个值绑定到所有字段。长话短说 - 改变模型中的字段名称,使它们不同。

+0

我找到了一个替代解决方案(请参阅上面的答案),但是如果更改这些字段名称,则允许我的旧代码按写入方式工作? – DeltaG

+0

是的,虽然我认为我更喜欢你的解决方案,但我可以很容易地想象出一种情况,即改变模型字段名至少是麻烦的。 – rafalmp

0

由于您的CourseSection都有所谓Name的属性,我打赌你的形式与属性id = "id_Name"name = "Name"两个字段。