在 Django 中使用 inlineformset_factory 时将模型用户设置为当前用户

Setting model user to current user when using inlineformset_factory in Django

我遇到了我花了几个小时试图克服的障碍,我希望得到一些指导。

我有两个模型:Listings 和 Addresses,结构如下:

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 class 中使用 "exclude = ['user']" 而不是 "fields = ['user']",但结果是创建了一个新地址,但没有创建一个列表来配合它。所以我得到的只是一个新地址,没有列表。

我做错了什么?我将非常感谢解决这个问题,因为很长一段时间以来我一直在用头撞墙!

在这种情况下,我根本不会使用表单集。如果您需要收集用户信息以创建新列表,请使用单个 ListingFormAddressForm,保存新地址,然后使用 commit=False 保存 ListingForm,分配用户和地址,然后保存实例。

@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