Django保存相关多个模型
我有两个模型,它们之间有很多关系:Django保存相关多个模型,django,django-forms,django-views,Django,Django Forms,Django Views,我有两个模型,它们之间有很多关系: class Subject(models.Model): teachers = models.ManyToManyField( Teacher ) subject = models.CharField( 'Materia', max_length = 50, unique = True ) level = models.CharField( 'Nivel
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
我知道我可以在不保存教师字段的情况下保存科目模型。那很好
现在我想向教师添加一个科目,因此我需要一个包含选定教师的表单,以及一个包含所有科目的选择字段。
这与我想要实现的目标有关,但我认为这并不能解决我想要实现的目标
首先,我填充subject choice字段,如下面的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']
#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'),
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
url.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']
#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'),
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 }}
所以,很明显我做错了什么
我的问题是,我是否可以使用基于类的视图来实现这一点,或者我应该编写一个方法来保存关系,以及我应该在代码中更改什么
我想我说得够清楚了,谢谢。我想你需要一个特定的
获取对象()
从教师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])
指定为列表self.object.teachers.add([teacher])我认为您需要一个特定的get\u object()
从教师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])
分配为一个列表self.object.teachers.add([teacher])您需要调用super(SubjectTeacherCreateView,self.form\u-valid(form)
中的self即可获得self.object,这是覆盖前的sourceform\u Availd
方法:
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()
您需要调用super(SubjectTeacherCreateView,self)。在您的form\u valid
中,form\u valid(form)
,然后您可以获得self.object
,这是覆盖之前的sourceform\u availd
方法:
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()
这就是我要找的。但我现在意识到的一个细节是,我不需要模板中的输入教师,因为我可以在视图中捕获和处理它。因此,有效的方法是teacher=teacher.objects.get(pk=self.kwargs['teacher\u id'])尝试:materia=materia.objects.get(id=form.cleaned\u data['materia'])materia.teachers.add(teacher)
我的逻辑是选择一个特定的老师,然后添加主题。你是指这个吗?你的ModelForm
中的通知老师是SelectMultiple widget?你不知道,我在哪里定义SelectMultiple widget?ModelForm中的老师正在映射到SelectMultiple widget,但我不明白为什么你的主题TeacherForm中需要老师?这就是我一直在寻找的。但我现在意识到的一个细节是,我不需要模板中的输入教师,因为我可以在视图中捕获和处理它。因此,有效的方法是teacher=teacher.objects.get(pk=self.kwargs['teacher\u id'])尝试:materia=materia.objects.get(id=form.cleaned\u data['materia'])materia.teachers.add(teacher)
我的逻辑是选择一个特定的老师,然后添加主题。你指的是这个吗?ModelForm
中的通知老师是SelectMultiple widget?我不知道,我在哪里定义SelectMultiple widget?ModelForm中的老师映射到SelectMultiple widget,但我不明白你为什么需要SubjectTeacherForm中的老师?