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

Posted

技术标签:

【中文标题】Django 表单视图:M 到 M 值未保存【英文标题】:Django Form View: M to M values not saved 【发布时间】:2015-04-17 22:11:28 【问题描述】:

我的 Django 应用程序中有以下设置:

观看次数

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 中吗?真的没有人知道我该如何解决这个问题吗:/?

【问题讨论】:

您如何知道是否出现错误?您不会在模板上显示任何表单字段或错误。该表单几乎可以肯定是无效的,但您永远不会告诉用户。 【参考方案1】:

这就是commit=False 的保存方式,如the documentation 中所述:

当您的模型与另一个模型具有多对多关系时,会看到使用 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)

【讨论】:

啊抱歉,方法是添加到表单中,而不是对象中。【参考方案2】:

这里的代码似乎有点不正确,可以帮助您追踪问题的一些更新是:

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

【讨论】:

以上是关于Django 表单视图:M 到 M 值未保存的主要内容,如果未能解决你的问题,请参考以下文章

从视图中使用Django保存表单

在Django中将计算值从视图保存到模型

Django Forms - 保存后重定向

django表单提交后如何用弹框提示成功?

Django:表单未保存到数据库

纯Django表格绑定用户提交表格和视图