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,这是覆盖前的source
form\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
,这是覆盖之前的source
form\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中的老师?