2016-12-22 54 views
0

我已經打了一個我花了數小時努力克服的障礙,我將不勝感激一些指導。在Django中使用inlineformset_factory時,將模型用戶設置爲當前用戶

我有兩個型號:房源和地址,具有以下結構:

class Listings(models.Model): 
    created_date = models.DateTimeField(auto_now_add=True) 
    pub_date = models.DateTimeField(auto_now_add=True) 
    address = models.ForeignKey(Addresses) 
    user = models.ForeignKey(User, on_delete=models.CASCADE) 
    is_active = models.BooleanField(default=1) 

class Addresses(models.Model): 
    address1 = models.CharField(max_length=100) 
    address2 = models.CharField(max_length=100) 
    address3 = models.CharField(max_length=100) 
    address4 = models.CharField(max_length=100) 
    postcode = models.CharField(max_length=8) 

我也有這些:

class AddressForm(ModelForm): 
    class Meta: 
     model = Addresses 
     fields = ['address1', 'address2', 'address3', 'address4', 'postcode'] 

class ListingForm(ModelForm): 
    class Meta: 
     model = Listings 
     fields = ['user'] 

我試圖創建一個表單,這將增加一個新的列表,但是輸入的唯一信息是地址模型中的字段。當表單提交時,我需要一個新的Listings對象和一個新的Addresses對象來創建,但是這個Listings對象必須有'user'外鍵等於當前登錄用戶的id。

這是視圖:

@login_required(login_url='share:login_view',   redirect_field_name='share:addlisting') 
def addlisting(request): 

    ListingInlineFormSet = inlineformset_factory(Addresses, Listings, form=ListingForm, can_delete=False, extra=1) 

    if request.method == 'POST': 

     address_form = AddressForm(request.POST) 
     if address_form.is_valid(): 
      new_address = address_form.save() 
      listing_formset = ListingInlineFormSet(request.POST, request.FILES, instance=new_address) 

      if listing_formset.is_valid(): 
       listing_formset.save() 
       return HttpResponseRedirect(reverse('/listing_added/')) 

    else: 
     address_form = AddressForm() 
     listing_formset = ListingInlineFormSet() 

    return render(request, 'share/addlisting.html', { 
     "address_form": address_form, 
     "listing_formset": listing_formset, 
    }) 

在當前狀態下,我得到一個包含所有的地址字段,再加上一個下拉用戶域的表單。提交表單時,它會創建一個包含兩個外鍵的新列表:一個用於所選用戶,另一個用於剛剛創建的新地址。這最終結果是我想要的。但是,我不希望那裏有一個下拉式用戶字段 - 我需要將用戶設置爲當前用戶。我嘗試在ListingForm類中使用「exclude = ['user']」,而不是「fields = ['user']」,但是這樣做的結果是創建一個新地址而不創建列表。所以我得到的只是一個新地址,沒有列出。

我在做什麼錯?我會很感激這個解決方案,因爲我已經把頭撞在牆上很長時間了!

+0

我應該提到的原因包括ListingForm(而不是僅僅具有AddressForm)是我計劃在適當的時候在表單中包含其他字段(這將成爲Listings對象的一部分) - 我只是想首先獲得表單結構。我有理由希望將地址與列表分開,因此不要將地址放入列表對象中。 – Kate

回答

1

在這種情況下,我根本不會使用formset。如果您需要收集用戶信息以創建新列表,請使用單個ListingFormAddressForm,保存新地址,然後將ListingForm保存爲commit=False,將用戶和地址分配給它,然後保存該實例。

@login_required(login_url='share:login_view', redirect_field_name='share:addlisting') 
def addlisting(request): 
    if request.method == 'POST': 
     address_form = AddressForm(request.POST, prefix="address") 
     listing_form = ListingForm(request.POST, prefix="listing") 
     if address_form.is_valid() and listing_form.is_valid(): 
      new_address = address_form.save() 
      new_listing = listing_form.save(commit=False) 
      new_listing.address = new_address 
      new_listing.user = request.user 
      new_listing.save() 
      return HttpResponseRedirect(reverse('/listing_added/')) 
    else: 
     address_form = AddressForm(prefix="address") 
     listing_form = ListingForm(prefix="listing") 
    return render(request, 'share/addlisting.html', { 
     "address_form": address_form, 
     "listing_form": listing_form 
    }) 

如果你有Listings一個多一對多的關係,你需要明確地拯救那些保存實例後,爲這裏討論: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#the-save-method

+0

啊,我應該提到,我打算在列表表單中添加更多字段,並且我有理由希望將地址保存在單獨的表中... – Kate

+0

在這種情況下,您希望省略「用戶「字段,並只指定您想要從用戶收集的值。然後使用'listing_form.save(commit = False)'在內存中實例化新列表,設置其用戶和地址屬性('new_listing.address = new_address; new_listing.user = request.user'),然後保存新的實例。上述內容沒有改變地址是否在單獨的表格中。 –

+0

如果你想使用formset來向用戶展示他們當前的列表並添加一個新的列表,那麼上面的設計應該合理順利地轉換成formset - 我可能仍然將用戶排除在外並明確地將其設置在任何更改的實例上,這比使用隱藏的輸入小部件更有控制。 –

相關問題