Django 表单视图:M 到 M 值未保存
Django Form View: M to M values not saved
我的 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 %}
你们知道为什么这没有按预期工作吗?
当我提交我的表单时,我没有收到任何错误,只是创建了学习 objective 而不是主题。
编辑 我现在对很多模型都使用这种方法。除多对多字段外,每个字段都有一个条目。提交表单时它们仍然为空。
我的一部分 self.request
:
POST:<QueryDict: {u'topic': [u'2'], u'csrfmiddlewaretoken': [u'362xs1yPTk84nXencmqxuXkKKaq5ARKF'], u'learning_objective': [u'weq']}>,
由于这是一个查询集,我能否以某种方式获取它的值并将其保存在我的 FormView
中?真的没有人知道我该如何解决这个问题吗:/?
这里的代码似乎有点不正确,可以帮助您跟踪问题的几个更新是:
- 在您的 CreateModel 视图中定义:form_class = LearningObjectiveForm,模型 = LearningObjective
- 在您的模板中使用这里https://docs.djangoproject.com/en/1.7/topics/forms/#rendering-fields-manually提到的表格
- 再次从 CreateModel View 的 form_valid 方法中删除超级调用,因为这将再次调用 form.save()(可能会在此处创建重复对象)
- 我不确定我是否看到 RetrieveLearningObjective 视图的相关性。
这就是使用 commit=False
进行保存的方式,如 the documentation 中所述:
Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.
To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.
解决方案是调用 form.save_m2m()
,这是在使用 commit=False
.
调用表单的 save
方法时添加到表单实例的方法
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)
我的 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 %}
你们知道为什么这没有按预期工作吗?
当我提交我的表单时,我没有收到任何错误,只是创建了学习 objective 而不是主题。
编辑 我现在对很多模型都使用这种方法。除多对多字段外,每个字段都有一个条目。提交表单时它们仍然为空。
我的一部分 self.request
:
POST:<QueryDict: {u'topic': [u'2'], u'csrfmiddlewaretoken': [u'362xs1yPTk84nXencmqxuXkKKaq5ARKF'], u'learning_objective': [u'weq']}>,
由于这是一个查询集,我能否以某种方式获取它的值并将其保存在我的 FormView
中?真的没有人知道我该如何解决这个问题吗:/?
这里的代码似乎有点不正确,可以帮助您跟踪问题的几个更新是:
- 在您的 CreateModel 视图中定义:form_class = LearningObjectiveForm,模型 = LearningObjective
- 在您的模板中使用这里https://docs.djangoproject.com/en/1.7/topics/forms/#rendering-fields-manually提到的表格
- 再次从 CreateModel View 的 form_valid 方法中删除超级调用,因为这将再次调用 form.save()(可能会在此处创建重复对象)
- 我不确定我是否看到 RetrieveLearningObjective 视图的相关性。
这就是使用 commit=False
进行保存的方式,如 the documentation 中所述:
Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.
To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.
解决方案是调用 form.save_m2m()
,这是在使用 commit=False
.
save
方法时添加到表单实例的方法
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)