如何从Django中的ModelForm中保存ManyToMany关系

时间:2011-05-03 23:36:11

标签: django

我不确定要保存我的ManyToMany关系。我在这个帖子中发现了我的确切问题:Django embedded ManyToMany form,除了销售和产品模型,我有构成电影的模型。

我尝试了解决方案,但收到语法错误。我不明白Django应该如何将EquipmentModel,LightModel和ActorModel链接到MovieModel中的ManyToMany关系。到目前为止(在尝试其他线程的解决方案之前),LightModel,EquipmentModel和ActorModel表单上显示的CharField都没有链接到MovieModel中的ManyToManyField。因此,当我保存表单并尝试访问特定电影的演员时,我看到的只是一个空白列表。来自其他线程的解决方案似乎有意义,因为它试图将模型链接到MovieModel中的ManyToMany关系,但我不明白Django如何知道要添加哪个MovieModel(如何获得正确的movieID?)。 / p>

另外,当用户按下表单上的“提交”按钮时,有没有办法检查重复的电影?我想避免创建重复项。

views.py:

def add_movie(request, movieID=""):

    if request.method == "POST":
            form = MovieModelForm(request.POST)
            eform = EquipmentModelForm(request.POST)
            lform = LightModelForm(request.POST)
            aform = ActorModelForm(request.POST)

            print 'checking form'
            print request.POST.items()
            if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
                    print 'form is valid'
                    movie_to_add = form.save()
                    e = eform.save()
                    l = lform.save()
                    a = aform.save()
                    movie_to_add.actors.add(a)
                    movie_to_add.lights.add(l)
                    movie_to_add.equipments.add(e)

            #       return HttpResponseRedirect('/data')
    else:
           # code for create forms ....


    return render_to_response('add_movie.html', {'form':form, 'eform':eform,'lform':lform, 'aform':aform,}, context_instance=RequestContext(request))

其他可能有用的代码:

forms.py

class LightModelForm(forms.ModelForm):
    class Meta:
            model = LightModel

class ActorModelForm(forms.ModelForm):
    class Meta:
            model = ActorModel

class EquipmentModelForm(forms.ModelForm):
    class Meta:
            model = EquipmentModel

class MovieModelForm(forms.ModelForm):

    class Meta:
            model = MovieModel
            fields = ("title", "rank")

models.py

class EquipmentModel(models.Model):
    equip = models.CharField(max_length=20)

class ActorModel(models.Model):
    actor = models.CharField(max_length=20)

class LightModel(models.Model):
    light = models.CharField(max_length=20)

class MovieModel(models.Model):
    rank = models.DecimalField(max_digits=5000, decimal_places=3)
    title = models.CharField(max_length=20)

    equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
    actors = models.ManyToManyField(ActorModel, blank=True, null=True)
    lights = models.ManyToManyField(LightModel, blank=True, null=True)

    def __str__(self):
            return self.title

编辑:感谢DTing

删除了不必要的 init 和字段

Edit2:已修复!

2 个答案:

答案 0 :(得分:2)

除了什么是spulec之外,还有很多东西出错了。

你的models.py看起来还不错。

class EquipmentModel(models.Model):
    equip = models.CharField(max_length=20)

class ActorModel(models.Model):
    actor = models.CharField(max_length=20)

class LightModel(models.Model):
    light = models.CharField(max_length=20)

class MovieModel(models.Model):
    rank = models.DecimalField(max_digits=5000, decimal_places=3)
    title = models.CharField(max_length=20)

    equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
    actors = models.ManyToManyField(ActorModel, blank=True, null=True)
    lights = models.ManyToManyField(LightModel, blank=True, null=True)

    def __str__(self):
            return self.title

如果您没有在init上更改任何内容,则无需覆盖表单上的__init__方法。如果要将这些字段全部包含在内,您也不需要明确这些字段。

class LightModelForm(forms.ModelForm):
    class Meta:
            model = LightModel

class ActorModelForm(forms.ModelForm):
    class Meta:
            model = ActorModel

class EquipmentModelForm(forms.ModelForm):
    class Meta:
            model = EquipmentModel

class MovieModelForm(forms.ModelForm):
    class Meta:
            model = MovieModel
            fields = ("title", "rank")

除非您尝试添加的每部电影都想要:

,否则您的观点确实没有意义
  1. 使用提交的帖子数据将新电影添加到数据库
  2. 创建一个actor对象并添加到db
  3. 创建一个轻量级对象并添加到db
  4. 创建一个设备对象并添加到db
  5. 将这三个对象添加到另一部电影的m2m关系中。
    • 这部电影是你从urlconf中提取并传递给你视图的一部电影,而不是你刚创建的那部电影。
  6. 这一切似乎有点奇怪。

    我认为您想要做的是创建所有设备,演员和灯光对象,使它们已经在您的数据库中,并在添加电影时使用默认的m2m formfield小部件来选择它们。

    这样:

    forms.py

    class MovieModelForm(forms.ModelForm):
        class Meta:
            model = MovieModel
    

    urls.py:

    url(r'^add_movie/$', add_movie)
    

    views.py:

    def add_movie(request):
        if request.method=='POST':
            form = MovieModelForm(request.POST)
            if form.is_valid():
                form.save()
                return HttpResponse('success')
        else:
            form = MovieModelForm()
    
        context = {'form':form }
    
        return render_to_response('some_template.html', context,context_instance=RequestContext(request))
    

    你可以将演员,灯光和设备添加到同一个表单中,但这对我来说现在写的有点多了。

    至于修改原始代码以将这些灯光,演员和设备添加到刚创建的电影中,您可以这样做:

            if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
                    new_movie = form.save()
                    e = eform.save()
                    l = lform.save()
                    a = aform.save()
                    new_movie.actors.add(a)
                    new_movie.lights.add(l)
                    new_movie.equipments.add(e)
    

答案 1 :(得分:0)

将其更改为:

movie_to_add = get_object_or_404(MovieModel, id=movieID)