Django m2m和保存对象

时间:2009-12-03 07:23:10

标签: django save many-to-many

我有一些具有多对多关系的简单对象。 Django使用obj1_obj2表加入了它们,它在mysql中看起来像这样;

id  |  person_id  |  nationality_id  
-----------------------------------  
 1  |     1       |      1  
 2  |     1       |      2  

现在当我保存obj1(在其形式中将obj2显示为Multi-select)时,obj1_obj2表中的id增加甚至是我没有更改它们。例如,我在其表单上更改obj1的基本字符字段并保存它,并且连接表中的数据似乎被删除并重新保存,从而为条目提供新的ID。

事实上,我不需要改变任何事情我只需要保存表格并发生同样的事情。

我在视图中所做的就是form.save(),没什么特别的。这是正常的方式吗?

编辑:添加了模型,视图,表单

class Person(models.Model):
    name = models.CharField()  
    birthdate = models.CharField()  
    nationality = models.ManyToMany(Nationality)


class Employee(Person):
    employeeNum = models.CharField()


class FamilyMember(Person):  
    employee = models.ForeignKey(Employee)
    relationship = models.CharField()


class Nationality(models.Model):
    abbrev = models.CharField()
    country = models.CharField()


class FamilyMemberDetailsForm(forms.ModelForm):
    class Meta:
        model = FamilyMemeber
        exclude = ['employee']


def editFamilyMember(request, familyMember_id):
    familyMember = get_object_404(FamilMember, familyMember_id)
    if request.method == 'POST':
        form = FamilyMemberDetailsForm(request.POST, instance=familyMember)
        if form.is_valid():  
          form.save()
    else:
        form = FamilyMemberDetailsForm(instance=familyMember) 


    return render_to_response(editForm.html, {'form':form},  
                              context_instance(RequestContext(request))

这是模型的简化版本,但保存员工或家庭成员的情况也是如此。我已经展示了FamilyMember,因为它就像我创建modelForm然后进行更改然后保存它一样简单。对于员工,我在国籍表格的 init 中进行了一些操作,主要用于演示,起初我认为正是这种操作导致了它,但正如我所说同样的事情发生了和FamilyMember一起,除了保存,我什么都不做。

国籍在表单上显示为带有列表的多选框,用户可以从列表中选择1个或更多。如果我只显示填充的表单,然后保存它而不更改任何内容,多对多表条目的ID更改。

我也更改了示例表标题。

谢谢,
安德鲁

1 个答案:

答案 0 :(得分:2)

是的,在为具有ManyToManyField的对象保存表单时,删除appname_obj1_obj2中的任何现有行都是预期的行为。

你可以在django / db / models / fields / related.py中的ReverseManyRelatedObjectsDescriptor和ManyRelatedObjectsDescriptor中的add(**值)之前看到clear()。

弹出一个shell并亲自查看一下这些查询。这样的东西应该在原始sql中的INSERT之前显示DELETE。

from django.db import connection
fm = FamilyMember.objects.get(pk=1)
form = FamilyMemberDetailsForm(instance=fm)
data = form.initial
data['name'] = "z%s" % data['name']  
form = FamilyMemberDetailsForm(data, instance=fm)
connection.queries = []  # clearing to limit the queries you have to look at
form.save()
for q in connection.queries:
    print("%s\n" % q['sql'])