'Django How to Upload an Image to Form

This is my code associated with the form:

# models

class Date(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    place = models.ForeignKey('Place', on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=64, null=True)


class Photo(models.Model):
    date = models.ForeignKey('Date', on_delete=models.CASCADE)
    image = models.ImageField(verbose_name='Photos', upload_to='media/date/photos/')

# form

class DateForm(forms.ModelForm):
    image = forms.ImageField()
    class Meta:
        model = Date
        exclude = ('user',)

# view

class CreateDateView(LoginRequiredMixin, CreateView):
    template_name = 'app/date/form.html'
    form_class = DateForm

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.save() # by the way why do I save this form? Is it okay to save it in form_valid method?
        photos = self.request.FILES.getlist('image')
        for photo in photos:
            Photo.objects.create(image=photo)
        return super().form_valid(form)

The issue is how to save Photo objects if it requires a Date model id. It raises NOT NULL constraint failed: app_photo.date_id As I understand I have to write something like:

Photo.objects.create(date=date_from_the_form, image=photo)

But how to get the pk from the Date model? Hope you understand my problem, if any questions don't hesitate to write down below in comments section. Thanks in advance!

Error



Solution 1:[1]

You need to create the date object first. Also, is each date going to be unique? If so, you need to change your model Meta declarations to include unique_together.

You also need to avoid the for loop when creating each object. It's very expensive because it's going to make a round trip to the database for each save() called. That's what bulk_create is for, which limits your database touches to one command to make many objects.

Here's pseudocode to get you going:

if len(photos) > 0:  # don't create a date if there aren't photos
  date = Date() # add your arguments

  filtered = Date.objects.filter(date=date)

  date = date.create() if not filtered.exists() else date = filtered[0]  # but this is potentially dangerous if you risk duplicate dates. Only use this if you know it's the correct date
  photos = [Photo(date=date,image=p) for p in photos]
  Photo.objects.bulk_create(photos)

Good luck!

Solution 2:[2]

You need save the photo object:

def form_valid(self, form):
    form.instance.user = self.request.user
    form.save() # by the way why do I save this form? Is it okay to save it in form_valid method?
    photos = self.request.FILES.getlist('image')
    for photo in photos:
        temp = Photo.objects.create(image=photo)
        temp.save()
    return super().form_valid(form)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shaun Overton
Solution 2 LordPokerFace