I've hit a roadblock that I've spent hours trying to overcome, and I would appreciate some guidance.
I have two models: Listings and Addresses, with the following structure:
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)
I also have these:
class AddressForm(ModelForm):
class Meta:
model = Addresses
fields = ['address1', 'address2', 'address3', 'address4', 'postcode']
class ListingForm(ModelForm):
class Meta:
model = Listings
fields = ['user']
I'm trying to create a form which will add a new listing, however the only information to be entered are the fields in the Addresses model. When the form is submitted, I need a new Listings object and a new Addresses object to be created, but the Listings object must have the 'user' foreign key equal to the id of the current logged-in user.
This is the view:
@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,
})
In its current state, I get a form containing all the address fields, plus a drop-down user field. When the form is submitted, it creates a new listing with two foreign keys: one for the chosen user, and another for the new address that has just been created. This end result is what I want. HOWEVER, I don't want there to be a drop-down user field in the form - I need the user to be set to the current user. I tried using "exclude = ['user']" in the ListingForm class instead of "fields = ['user']", but this had the result of creating a new address without creating a listing to go with it. So all I got was a new address, and no listing.
What am I doing wrong? I would be so grateful for a solution to this, as I've been banging my head against a wall for a very long time!
In this case I wouldn't use a formset at all. If you need to collect user information to create the new listing, use a single
ListingForm
andAddressForm
, save the new address, and then save theListingForm
withcommit=False
, assign the user and address to it, and then save the instance.If you ever have a many-to-many relationship on
Listings
you'll need to explicitly save those after saving the instance, as discussed here: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#the-save-method