我有两个与ManyToMany关系的模型:
class Subject(models.Model):
teachers = models.ManyToManyField(
Teacher
)
subject = models.CharField(
'Materia',
max_length = 50,
unique = True
)
level = models.CharField(
'Nivel',
max_length = 3,
choices = LEVEL_CHOICES
)
class Teacher(Person):
# fields definition
Following the docs我知道我可以在不保存教师字段的情况下保存主题模型。没关系。
现在我想向教师添加一个主题,所以我需要一个包含所选教师的表单,以及一个包含所有主题的选择字段。
I found this question与我想要完成的事情相关,但我认为它并没有解决我正在寻找的问题。
首先,我填充主题选择字段,如下面的ModelForm代码所示。
forms.py
class SubjectTeacherForm(ModelForm):
subject = forms.ChoiceField(choices=[(m.id, m.subject) for m in Subject.objects.all()])
class Meta:
model = Subject
fields = ['teachers', 'subject']
urls.py
#here I send the teacher id to the view
url(r'^materias/asignar/profesor/(?P<teacher_id>\d+)/$',MateriaTeacherCreateView.as_view(), name='materia-create-teacher'),
views.py
class SubjectTeacherCreateView(SuccessMessageMixin, CreateView):
model = Subject
template_name = 'edu/subject/subject_create.html'
form_class = SubjectTeacherForm
def form_valid(self, form):
# here I want to add the relation
teacher = Teacher.objects.get(pk=self.kwargs['teacher_id'])
# I understad that object here is the ModelForm, not the Model, so this is wrong
self.object.teachers.add(teacher)
return redirect(self.get_success_url())
def get_context_data(self, **kwargs):
context = super(SubjectTeacherCreateView, self).get_context_data(**kwargs)
# here I define the selected teacher to pass to the template
context['teacher'] = Teacher.objects.get(pk=self.kwargs['teacher_id'])
return context
模板
<form method="post" class="form-horizontal">
{% csrf_token %}
{{ form.teacher }}
{{ form.subject }}
正如预期的那样,这不起作用,表单没有保存,它会抛出错误:
AttributeError at /edu/materias/asignar/profesor/11/
'NoneType' object has no attribute 'teachers'
所以,显然我做错了什么。
我的问题是我是否可以使用基于类的视图来完成此任务,或者我应该编写一个方法来保存关系,以及我应该在代码中更改什么。
我希望自己足够清楚,谢谢。
答案 0 :(得分:1)
您需要在super(SubjectTeacherCreateView, self).form_valid(form)
中拨打form_valid
,然后在覆盖之前获取self.object
,这是源form_vaild
方法:
def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
self.object = form.save()
return super(ModelFormMixin, self).form_valid(form)
但作为你的条件,这是正确的方法:
def form_valid(self, form):
try:
subject = Subject.object.get(id=form.cleaned_data['subject'])
teacher = Teacher.objects.get(pk=self.kwargs['teacher_id'])
subject.teachers.add(teacher)
except Subject.DoesNotExist:
# handle it youself
return redirect(self.get_success_url()
答案 1 :(得分:0)
我认为您需要一个特定的get_object()
才能从subject
中找到teacher_id
的对象。
def get_object(self):
teacher_id = self.kwargs['teacher_id']
subject = get_object_or_404(self.model, teachers__id=teacher_id)
return subject
并且,如果self.object.teachers.add(teacher)
不起作用,请尝试将其指定为列表self.object.teachers.add([teacher])
。