【问题标题】:Django save related ManyToMany modelDjango保存相关ManyToMany模型
【发布时间】:2017-11-08 23:23:53
【问题描述】:

我有两个具有多对多关系的模型:

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'

所以,显然我做错了什么。

我的问题是我是否可以使用基于类的视图来完成此操作,或者我应该编写一个方法来保存关系,以及我应该在我的代码中进行哪些更改。

我希望我说得够清楚了,谢谢。

【问题讨论】:

    标签: django django-forms django-views


    【解决方案1】:

    您需要在您的form_valid 中调用super(SubjectTeacherCreateView, self).form_valid(form),然后您可以获得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()
    

    【讨论】:

    • 这就是我想要的。但是我现在意识到的一个细节是我不需要模板中的输入老师,因为我可以在视图中捕获和处理它。所以有效的是teacher = Teacher.objects.get(pk=self.kwargs['teacher_id']) try: materia = Materia.objects.get(id=form.cleaned_data['materia']) materia.teachers.add(teacher)
    • 我的逻辑是我选择一个特定的老师,然后我添加科目。你指的是这个吗?
    • ModelForm 中的通知老师是 SelectMultiple 小部件吗?
    • 你把我弄丢了,我在哪里定义 SelectMultiple 小部件?
    • ModelForm 中的教师正在映射到 SelectMultiple 小部件,但我不明白为什么您的 SubjectTeacherForm 中需要教师?
    【解决方案2】:

    我认为您需要一个特定的get_object() 才能从teacher_id 中找到subject 的对象。

    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])

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-27
      • 2020-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      • 1970-01-01
      • 2011-05-10
      • 2015-04-12
      相关资源
      最近更新 更多