2014-03-31 35 views
0

一個關係,我有兩個型號許多在Django的

class Model_1(models.Model): 
    foreign_key_field = models.ForeignKey(Model_2) 

class Model_2(models.Model): 
    number = models.IntegerField() 

我需要的ModelForm編輯Model_2對象。在這種形式下,我想要一個所有Model_1對象的列表,以及複選框的選項,這些Model_1字段應該使用特定的Model_2對象作爲ForeignKey。

實際上,它應該像ManyToMany域一樣工作,但是在ManyToOne關係中。

也許可能的ModelForm看起來是這樣的:

class SetForeignKeyForm(ModelForm): 
    is_linked = BooleanField(required=False) 

    class Meta: 
     model = ModelName 
     fields =() 

    def clean_is_linked(self): 
     if self.cleaned_data['is_linked']: 
      self.fields['foreign_key_field'] = self.object 

和視圖:

class Model2UpdateView(ModelFormSetView): 
    model = Model_2 
    form_class = SetForeignKeyForm 

    def get_queryset(self): 
     return Model_2.objects.all() 

我不知道如何讓我定製的ModelForm的Model_2對象,所以我不不知道如何保存Model_1對象是否鏈接到特定的Model_2對象。

我將結束與一個輸出它看起來像

<h1>Model_2 object</h1> 
<form method="post" action=""> 
    <tr> 
    <td>Model1 object name</td> 
    <td><input type="checkbox" name="model1_id_1" /></td> 
    </td> 
    <tr> 
    <td>Model1 object name</td> 
    <td><input type="checkbox" name="model1_id_2" checked="checked" /></td> 
    </td> 
    <tr> 
    <td>Model1 object name</td> 
    <td><input type="checkbox" name="model1_id_3" /></td> 
    </tr> 
    <input type="submit" /> 
</form> 

編輯1

我做了什麼,似乎工作,但我不知道這是否是正確。

我有一個觀點

class Model2Detail(ModelFormSetView): 
    model = Model1 
    template_name = 'tpl.html' 
    form_class = PairingForm 
    extra = 0 

    def get_queryset(self): 
     self.object = get_object_or_404(Model2, slug=self.kwargs['slug']) 
     return Model1.objects.all() # those objects with ForeignKey field 

    def formset_valid(self, formset): 
     for form in formset: 
      form.instance.foreign_key_field = self.object # set Model1's ForeignKey field 
      form.save() 
     return HttpResponseRedirect(self.get_success_url()) 

    def get_success_url(self): 
     return self.object.get_absolute_url() 

和形式

class PairingForm(ModelForm): 
    is_linked = BooleanField(required=False) 

    class Meta: 
     fields =() 
     model = Model2 # those objects __without__ ForeignKey field 

    def __init__(self, *args, **kwargs): 
     super(PairingForm, self).__init__(*args, **kwargs) 
     if self.instance.foreign_key_field: # if object already paired 
      self.fields['is_linked'].initial = True 

    def save(self, commit=True, force_insert=False, force_update=False, *args, **kwargs): 
     obj = super(PairingForm, self).save(commit=False, *args, **kwargs) 
     if self.cleaned_data['is_linked']: 
      obj.foreign_key_field = self.instance.entry 
     else: 
      obj.foreign_key_field = None # remove pairing 
     obj.save() 

對我來說,似乎是錯誤的,我嘗試設置在兩個視圖和形式ForeignKey的領域,但我不知道應該如何。

編輯2

我的代碼工作,但其實我不知道爲什麼。如果我不在formset_valid中設置外鍵字段,它不再起作用,所以我認爲出了問題。難道我不能在沒有覆蓋formset_valid的情況下工作嗎?我是否在我的表單中使用Meta.model中的正確模型?

回答

0

我認爲修改窗體中只有一種類型的對象是一種很好的做法。這使得事情分離開來,並且我相信,這會導致一個更清晰的設計和預期的行爲。考慮到這一點,我認爲你不應該認爲這不是「編輯Model_2對象」,而是更多地「編輯一堆Model_1對象」,方法是在每個對象上設置或取消設置值。在該體系結構中,您可以使用表單集,每個表單集都有一個複選框字段(例如,is_linked)。在formset的save_newsave_existing方法中,您可以檢查該字段並相應地在要保存的特定對象上設置外鍵。

您的更新版本看起來不錯。我看到的唯一問題是您的formset_valid方法似乎爲表單中的每個對象設置了外鍵字段,但您真的只希望在is_linked爲True時設置它,對嗎?在我看來,ParingForm實際上在保存時是正確的,因此您不需要在formset_valid中設置值。

+0

好主意。但是,如果formset中的對象和特定窗體已鏈接,如何將複選框標記爲已選中?我已經瀏覽了文檔,但似乎無法找到解決方法。 – Jamgreen

+0

在表單集的情況下,'initial'參數是一個字典列表,它可能會給你你想要的。你也可以考慮重寫'add_field'方法。 – DavidM

+0

我做了一個編輯。這是對的嗎? – Jamgreen