如何使用直通关系保存ManyToMany字段

ali*_*s51 6 django many-to-many django-models django-forms django-views

我有以下模型与a ManyToManythrough关系:

class Meeting(models.Model):
    site = models.ForeignKey(Site)
    meeting_title = models.CharField(default='', max_length=128, blank=True, null=True)
    meeting_visitors = models.ManyToManyField(Visitor, through="MeetingArrival", blank=False, null=False) 

class Visitor(models.Model):
    visitor_company = models.ForeignKey(Company)
    visitor_name = models.CharField(default='', max_length=128, blank=False, null=False)

class MeetingArrival(models.Model):
    visitor = models.ForeignKey(Visitor)
    meeting = models.ForeignKey(Meeting)
    arrival_status = models.BooleanField(default=False)
Run Code Online (Sandbox Code Playgroud)

我有一个表单来创建会议:

class AddMeetingForm(forms.ModelForm):

    class Meta:
        model = Meeting
        exclude = ['site',]
Run Code Online (Sandbox Code Playgroud)

以及保存表单的简单视图:

def add_meeting(request): 
    add_meeting_form = AddMeetingForm(request.POST or None)
    site = Site.objects.get(user=request.user.id)

    if request.method == "POST":
        if add_meeting_form.is_valid():

            obj = add_meeting_form.save(commit=False)
            obj.site = site
            obj.save()
Run Code Online (Sandbox Code Playgroud)

这样可以保存表单,但不保存meeting_visitors字段,即使此字段在视图中完美呈现.我如何保存这种关系?

编辑

如果我添加add_meeting_form.save_m2m()到视图中,我会得到Cannot set values on a ManyToManyField which specifies an intermediary model. Use meetings.MeetingArrival's Manager instead..我该怎么做?

Rah*_*pta 14

您必须MeetingArrival在视图中显式保存对象,以便在ManyToManyField带有through参数的情况下保存中间模型.

在的情况下,ManyToManyField与中介模式,则不能使用add,create或者assignment它们可与普通多到很多领域.

根据Django文档:

与普通的多对多字段不同,您不能使用添加,创建或分配来创建关系.

创建此类关系的唯一方法是创建中间模型的实例.

因此,您必须MeetingArrival在视图中显式创建对象.

你可以这样做:

def add_meeting(request): 
    add_meeting_form = AddMeetingForm(request.POST or None)
    site = Site.objects.get(user=request.user.id)

    if request.method == "POST":
        if add_meeting_form.is_valid():
            obj = add_meeting_form.save(commit=False)
            obj.site = site
            obj.save()

            # create an instance of 'MeetingArrival' object
            meeting_arrival_obj = MeetingArrival(meeting=obj, visitor=<your_visitor_object_here>, arrival_status=True)
            meeting_arrival_obj.save() # save the object in the db
Run Code Online (Sandbox Code Playgroud)


小智 5

Django的1.x中,它是什么拉胡尔说,你不能使用addcreate

对于 django 2.x,您实际上可以根据此处的文档django 2.x

您还可以使用 add()、create() 或 set() 来创建关系,只要您为任何必填字段指定 through_defaults:

beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)})
beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)})
beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
Run Code Online (Sandbox Code Playgroud)