0

I have 2 models Listing and Image, where a listing can have multiple images.

class Listing(models.Model):
    title = models.CharField(max_length=100, blank=False)

class ListingImage(models.Model):
    listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name='images')
    image = models.ImageField(blank=True)

Ideally, I wanted to create such listings on a single page e.g. fill in all form information AND add images on the same page.

It seems that this is not possible (if it's please let me know, but note that dropzone.js is Ajax) to handle 2 forms with a single view and I have made the following workarounds:

  1. Create listings first, add 2nd step to add listings to created model
  2. Create a placeholder listing, add images to it (via Ajax) and on form submit, change the placeholder information.

Which method is better?

views.py

def add_image(request):
# process images: problem we have no listing_instance to add them to
    if request.method == 'POST':
        form = ListingImageForm(request.POST, request.FILES)
        if form.is_valid():
            ListingImage.objects.create(pk=None, listing=listing_instance)

            return HttpResponse(
                json.dumps({
                    "result": True,
                }),
                content_type="application/json"
            )

I'm looking for methodology advice. For example, to create a listing with images, do I need to first create the listing and then add images (2 steps) or add images first and listing information? My problem is that if I do that, the listing is not yet created when I add the images using Ajax.

GRS
  • 2,807
  • 4
  • 34
  • 72
  • It is possible to have 2 forms in a single view. See: [How can I build multiple submit buttons django form?](https://stackoverflow.com/q/866272/5371551) – Shivam Singh Jun 05 '18 at 16:38
  • @ShivamSingh The problem is with processing the second form, because it's related to the first form, which hasn't been created in our case – GRS Jun 05 '18 at 16:47

1 Answers1

1

I'll propose my solution which I've implemented in my projects and works like a charm.

  1. form is rendered, dropzone.js initialized
  2. images are submitted and uploaded to the defined endpoint (url), here django view saves uploaded file (as a model), returns saved image pk (or other unique identifier).
  3. client front-end receives saved image pk and stores in the hidden input (for ex. named images) with some kind of protocol (for ex. pk1::pk2::pk3)
  4. once form is submitted, django form validation has passed, you are processing input value with image pks and get entries from db: images = ListingImage.objects.filter(pk__in=request.POST.get('images').split('::'))
    I strongly recommend to apply more validation to images value This query will give you all user uploaded images for submitted form, and finally you will update ListingImage entries to link Listing entry images.update(listing=newly_created_listing_entry)

In addition, to avoid db bloating, I run cron job every 1 day to clean images which are not linked to any form (in case user abandoned form submission)

hope, this helps