Django表单视图:M到M值未保存

时间:2015-02-17 08:33:59

标签: django django-forms django-templates django-class-based-views

我在Django App中进行了以下设置:

视图

class LearningObjectiveView( LoginRequiredMixin, FormView ):
  form_class = LearningObjectiveForm
  success_url = reverse_lazy( 'learning_objective' )
  template_name = 'learningobjective.html'

  def get_context_data( self, **kwargs ):
    trainee = Trainee.objects.get( username = self.request.user )
    context = super( LearningObjectiveView, self ).get_context_data( **kwargs )
    context['learningobjective'] = LearningObjective.objects.filter( trainee = trainee.id )
    context['topic'] = Topic.objects.filter( trainee = trainee.id )
    return context

  def form_valid( self, form ):
    self.object = form.save( commit = False )
    if self.request.user.is_authenticated():
      self.object.trainee = Trainee.objects.get( username = self.request.user )
    self.object.save()
    return super( LearningObjectiveView, self ).form_valid( form )

模型

class Topic( models.Model ):
  trainee = models.ForeignKey( Trainee )
  topic = models.TextField()

class LearningObjective( models.Model ):
  trainee = models.ForeignKey( Trainee )
  topic = models.ManyToManyField( Topic, blank = True, null = True )
  learning_objective = models.TextField()

形式

class LearningObjectiveForm( ModelForm ):
  class Meta:
    model = LearningObjective
    fields = ( 'learning_objective', 'topic', )

模板

{% extends "base.html" %}


{% block body %}

<table border="1">
 <th>Delete</th>
 <th>Lernziel</th>
 <th>Thema</th>
 {% for learningobj in learningobjective %}
  <tr>
   <td><a href="{% url 'learning_objective_delete' pk=learningobj.pk %}">Delete</a></td>
   <td>{{ learningobj.learning_objective }}</td>
   <td>{% for t in learningobj.topic.all %}{{ t.topic }}{% endfor %}</td>
  </tr>
 {% endfor %}
</table>

<form method="POST" action="{% url 'learning_objective_create' %}">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type="submit" value="Speichern"/>
</form>

{% endblock %}

你们知道为什么这不能按预期工作吗?

当我提交表单时,我没有收到任何错误,只是创建了学习目标,但没有创建主题。

编辑我现在为许多模型使用了这种方法。每个字段都有一个条目,除了多个到多个字段。提交表格时,它们仍然是空的。

self.request的一部分:

POST:<QueryDict: {u'topic': [u'2'], u'csrfmiddlewaretoken': [u'362xs1yPTk84nXencmqxuXkKKaq5ARKF'], u'learning_objective': [u'weq']}>,

由于这是一个查询集,我可以以某种方式获取它的值并将其保存在我的FormView中吗?真的没有人知道如何解决这个问题:/?

2 个答案:

答案 0 :(得分:1)

正如the documentation中提到的那样commit=False的保存工作原理如下:

  

当您的模型与另一个模型具有多对多关系时,可以看到使用commit = False的另一个副作用。如果模型具有多对多关系,并且在保存表单时指定commit = False,则Django无法立即保存多对多关系的表单数据。这是因为在实例存在于数据库中之前,无法为实例保存多对多数据。

     

要解决此问题,每次使用commit = False保存表单时,Django都会向您的ModelForm子类添加save_m2m()方法。手动保存表单生成的实例后,可以调用save_m2m()来保存多对多表单数据。

解决方案是调用form.save_m2m(),这是一种在使用save调用表单的commit=False方法时添加到表单实例的方法。

def form_valid(self, form):
    self.object = form.save(commit=False)
    if self.request.user.is_authenticated():
        self.object.trainee = Trainee.objects.get(username=self.request.user)
    self.object.save()
    form.save_m2m()
    return super(LearningObjectiveView, self).form_valid(form)

答案 1 :(得分:0)

此处的代码似乎有点不正确,很少有可以帮助您跟踪问题的更新:

  • 在您的CreateModel视图中,定义:form_class = LearningObjectiveForm,model = LearningObjective
  • 使用模板中提到的表单https://docs.djangoproject.com/en/1.7/topics/forms/#rendering-fields-manually
  • 再次从CreateModel View的form_valid方法中删除超级调用,因为这将再次调用form.save()(可能会在此处创建一个重复的对象)
  • 我不确定我是否看到了RetrieveLearningObjective View的相关性。