2009-12-03 99 views
1

我有一對簡單的對象,它們具有多對多的關係。 Django使用obj1_obj2表加入了它們,它在mysql中看起來像這樣;Django m2m並保存對象

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

現在,當我保存OBJ1(這表明在OBJ2在其形式多選)在obj1_obj2表增加的ID甚至thow我並沒有改變他們。例如,我在其窗體上更改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。我已經展示了FamilyMember,因爲它非常簡單,我創建了modelForm,然後進行更改並保存。對於員工,我在國籍表格的init中做了一些更多的操作,主要是爲了介紹,起初我認爲這是造成這種操作的操作,但正如我所說的,家庭成員也發生了同樣的情況,除了保存,什麼也不做

國籍在表單上作爲帶列表的多選框呈現,用戶可以從列表中選擇1個或多個。如果我只展示填充的表單,然後保存它而不更改多對多表條目更改的標識。

我也更改了示例表格標題。

感謝,
安德魯

+0

obj1_obj2表是否確實將id設置爲1或僅僅是一個錯字? – lemonad 2009-12-03 08:21:33

+0

請顯示您的觀點代碼。 – 2009-12-03 09:36:09

+0

我第二個代碼的請求...我不認爲我對我的m2m關係有這種影響 – Jiaaro 2009-12-03 17:08:05

回答

2

是的,在appname_obj1_obj2任何現有行的缺失是預期的行爲儲蓄具有ManyToManyField對象的形式時。

您可以在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']) 
+0

那麼有沒有可以避免這種情況?我應該在保存表格之前做一個測試,看看這個多對多情況是否發生了變化,是否有一個標準的方式來完成這個工作,還是僅僅將它看作是一個問題? – 2009-12-06 13:23:00

+0

您可以自己管理交接表中的實體,但問問自己是否值得在開始此路徑之前付出努力。這張表很小,無疑充分索引,所以它的操作應該非常快。如果調用save(commit = False),則save_m2m()將在表單對象上變爲可用(而不是在save()中調用)。然後,您可以使用person.nationality.add()和.remove()爲您自己的m2m關係管理嘗試一下,而不是調用form.save_m2m()。再次,確保在save_m2m()之前這是值得花費時間的事情。 – istruble 2009-12-06 18:01:18

+0

您對花費的時間和價值的觀點是一致的。我想我會放棄它。感謝您的幫助。 – 2009-12-07 06:48:05